How to get the device fingerprint - codenameone

I am trying to integrate a payment API in my application and one of the required field is the device fingerprint. I have googled and all I got was the fingerprint scanner and touch Id support which aren't what I need. Any ideas?

Realistically speaking, perhaps the simplest thing you can do is not to obtain or calculate a unique device identifier, but to assign each specific installation of your app a unique code (which will therefore change if the app is uninstalled and reinstalled).
I'll try to give you an example.
In the init() method of the main class, you can add this code:
// Register the device (assigning it an unique deviceId)
// The deviceId is used also by: https://www.codenameone.com/javadoc/com/codename1/io/Util.html#getUUID--
registerDevice();
Your registerDevice() implementation could set the deviceId to identify this app installation. The best and most reliable solution, in this case, is to get a UUID from your server, e.g. like this code:
// Sets the device unique identifier
Rest.get(Server.getRestServerURL() + "/uniqueIdentifier").fetchAsString((Response<String> response) -> {
String deviceId = response.getResponseData();
Preferences.set("deviceId", deviceId);
Log.p("DeviceId: " + deviceId, Log.INFO);
});
The server-side code is quite simple. Staying in the Java world, and assuming we have a Spring Boot server, the code could be:
#GetMapping("/uniqueIdentifier")
#ResponseBody
public String uniqueIdentifier() {
return UUID.randomUUID().toString().replace("-", "");
}
This solution should be enough. Note that UUIDs must be unique, but they are not designed to be unpredictable. You can see a discussion about this here: https://stackoverflow.com/a/41156/1277576
Alternatively, if your code is to be client-side only, read this Javadoc carefully: https://www.codenameone.com/javadoc/com/codename1/io/Util.html#getUUID--
Util.getUUID() returns a pseudo-random Universally Unique Identifier in its canonical textual representation. This could be enough in most cases.
These are just basic suggestions. Obviously you will need to develop the code so that the deviceId is requested once.

Related

CPQ Quote API, I can't save the quote

I can't save the quote.
Doing the query:
select
ApexClass.name, Id, CreatedDate, CreatedById, JobType,
ApexClassId, Status, JobItemsProcessed, TotalJobItems,
NumberOfErrors, CompletedDate, MethodName, ExtendedStatus,
ParentJobId, LastProcessed, LastProcessedOffset
from
AsyncApexJob
order by
CreatedDate desc
I get this error:
Calculation error on quote Q-13761: "UNAUTHORIZED"
Code:
public with sharing class QuoteCalculator {
public void calculate(QuoteModel quote, String callbackClass) {
system.debug('quote: ' +quote);
system.debug('callbackClass: ' +callbackClass);
QuoteCalculatorContext ctx = new QuoteCalculatorContext(quote, callbackClass);
SBQQ.ServiceRouter.load('SBQQ.QuoteAPI.QuoteCalculator', null, JSON.serialize(ctx));
system.debug('QuoteCalculator.calculate');
}
private class QuoteCalculatorContext {
private QuoteModel quote; //The quote and callbackClass properties are called
in the API code by the exact names seen here.
private String callbackClass; //Altering these property names will cause
calculator API calls to fail.
private QuoteCalculatorContext(QuoteModel quote, String callbackClass) {
this.quote = quote;
this.callbackClass = callbackClass;
}
}
}
anonymous window:
QuoteReader reader = new QuoteReader();
QuoteModel quote = reader.read('a0p1w000BhfXzAAJ');
System.debug(quote);
quote.lineItems[0].record.SBQQ__Quantity__c = 2;
QuoteCalculator calculator = new QuoteCalculator();
calculator.calculate(quote, 'MyCallback')
Preface
I had (almost) the same exact code base as yours, and got the same error message.
In my case there was an other sandbox I could test my code, and it turned out to be working properly there.
Cause
Later found out that the Salesforce CPQ's Calculation Quote API is using Heroku to do the calculations in order to avoid apex limits exhaustion.
From this it can be deducted, that it needs to have a Connected App. I checked the Apps -> Connected Apps setup, and found that no record was listed under the "Connected Apps OAuth Usage" page for the Salesforce CPQ. (On my other sandbox there was a "Steelbrick CPQ" row.)
From this I concluded that this might be the reason for this behaviour.
Seems like something went wrong during the "Authorize new Calculation Service" process. (Or there was a sandbox refresh and something else went wrong during it.)
Solution
The bad news is that the option to authorize a new calculation service is only visible for the first time you configure the package, which you might already done. (Well... if you haven't done, then this is a great news, because your problem is probably solved. :D) (Otherwise read further.)
The good news is I figured out a solution for the case when you already done this, yet that "Steelbrick CPQ" row is missing.
Created a scratch org and installed the Salesforce CPQ package, then before I clicked on the "Authorize new Calculation Service" link under the "Pricing and Calculation" tab in the Settings Editor, I checked the source code in hope of finding something of interest.
I did.
This link: https://rest-na.steelbrick.com/oauth/auth/https%3A%2F%2Ftest.salesforce.com/SBQQ
(⚠️NOTE: You might have to change it according to your location. There are several servers across the globe:
rest-au.steelbrick.com
rest-eu.steelbrick.com
rest-jp.steelbrick.com
rest-na.steelbrick.com
But for me the above pasted link was generated on the settings page. Which is only interesting, because I live in the EU, yet, for some reason I got the link to the rest-NA server... whatever.gif
So just make sure if you click on the link, in the address bar you can find the appropriate salesforce instance URL.)
Conclusion
With this link you won't have to reinstall the package, you just have to click on it, and allow the access from Steelbrick and the missing row will appear, and you will be authorized to use the Calculation API.

How to send custom DocumentOperation to DocumentProcessing pipeline from a Processor?

Scenario: I've been stuck on this for way to long and I think solution might be easy but I just can't see it, this is the scenario:
cURL POST to http://localhost:8080/my_imports (raw JSON data on body)
->
MyImportsCustomHandler (extends ThreadedHttpRequestHandler [Validations]
->
MyObjectProcessor (extends Processor) [JSON deserialize and data massage]
->
MyFirstDocumentProcessor (extends DocumentProcessor) [Set some fields and save]
Problem is that execution never reaches MyFirstDocumentProcessor, likely because request didn't started from the document_api endpoints (intentionaly).
There are no errors thrown, just processing route never reaches the document processor chain, I think it should because on MyObjectProcessor I'm doing:
DocumentType type =
localDocHandler.getDocumentTypeManager().getDocumentType("my_doc");
DocumentId id = new DocumentId("id:default:my_doc::2");
Document document = new Document(type, id);
DocumentPut docPut = new DocumentPut(document);
Processing proc = com.yahoo.docproc.Processing.of(docPut);
I got this idea from here: https://github.com/vespa-engine/vespa/blob/master/docproc/src/test/java/com/yahoo/docproc/util/SplitterJoinerTestCase.java
but on that test I see this line splitter.process(p);, which I'm not able to find a suitable replacement that works inside a Processor, in that context I only have the Request, Execution and DocumentProcessingHandler
I hope somebody versed on Vespa con shine some light on this, is just the last hop on the processing chain that I can't bridge :|
To write documents from Java code, you need to use the Document Access API:
http://docs.vespa.ai/documentation/document-api-guide.html#document-access
A working solution is in https://github.com/vespa-engine/sample-apps/pull/44

Make a solr query from Geotools through geoserver

I come here because I am searching (like the title mentionned) to do a query from geotools (through geoserver) to get feature from a solr index.
To be more precise :
I saw on geoserver user manual that i can do query on solr like this in http :
http://localhost:8080/geoserver/wfs?service=WFS&version=1.1.0&request=GetFeature
&typeName=mySolrLayer
&format="xxx"
&viewparams=q:"mySolrQuery"
The important part on this URL is the viewparams that I want to use directly from geotools.
I have already test this case (this is a part of my code):
url = new URL(
"http://localhost:8080/geoserver/wfs?request=GetCapabilities&VERSION=1.1.0";
);
Map<String, String> param = new HashMap();
params.put(WFSDataStoreFactory.URL.key, url);
param.put("viewparams","q:myquery");
Hints hints = new Hints();
hints.put(Hints.VIRTUAL_TABLE_PARAMETERS, viewParams);
query.setHints(hints);
...
featureSource.getFeatures(query);
But here, it seems to doesn't work, the url send to geoserver is a normal "GET FEATURE" request without the viewparams parameter.
I tried this with geotools-12.2 ; geotools-13.2 and geotools-15-SNAPSHOT but I didn't succeed to pass the query, geoserver send me all the feature in my database and doesn't take "viewparams" as a param.
I need to do it like this because actually the query come from another program and I would easily communicate this query to another part of the project...
If someone can help me ?
There doesn't currently seem to be a way to do this in the GeoTool's WFSDatastore implementations as the GetFeature request is constructed from the URL provided by the getCapabilities document. This is as the standard requires but it may be worth making a feature enhancement request to allow clients to override this string (as QGIS does for example) which would let you specify the additional parameter in your base URL which would then be passed to the server as you need.
Unfortunately the WFS module lives in Unsupported land at present so unless you have resources to work on this issue yourself and can provide a PR to implement it there is not a great chance of it being implemented.

Parsing Swagger JSON data and storing it in .net class

I want to parse Swagger data from the JSON I get from {service}/swagger/docs/v1 into dynamically generated .NET class.
The problem I am facing is that different APIs can have different number of parameters and operations. How do I dynamically parse Swagger JSON data for different services?
My end result should be list of all APIs and it's operations in a variable on which I can perform search easily.
Did you ever find an answer for this? Today I wanted to do the same thing, so I used the AutoRest open source project from MSFT, https://github.com/Azure/autorest. While it looks like it's designed for generating client code (code to consume the API documented by your swagger document), at some point on the way producing this code it had to of done exactly what you asked in your question - parse the Swagger file and understand the operations, inputs and outputs the API supports.
In fact we can get at this information - AutoRest publically exposes this information.
So use nuget to install AutoRest. Then add a reference to AutoRest.core and AutoRest.Model.Swagger. So far I've just simply gone for:
using Microsoft.Rest.Generator;
using Microsoft.Rest.Generator.Utilities;
using System.IO;
...
var settings = new Settings();
settings.Modeler = "Swagger";
var mfs = new MemoryFileSystem();
mfs.WriteFile("AutoRest.json", File.ReadAllText("AutoRest.json"));
mfs.WriteFile("Swagger.json", File.ReadAllText("Swagger.json"));
settings.FileSystem = mfs;
var b = System.IO.File.Exists("AutoRest.json");
settings.Input = "Swagger.json";
Modeler modeler = Microsoft.Rest.Generator.Extensibility.ExtensionsLoader.GetModeler(settings);
Microsoft.Rest.Generator.ClientModel.ServiceClient serviceClient;
try
{
serviceClient = modeler.Build();
}
catch (Exception exception)
{
throw new Exception(String.Format("Something nasty hit the fan: {0}", exception.Message));
}
The swagger document you want to parse is called Swagger.json and is in your bin directory. The AutoRest.json file you can grab from their GitHub (https://github.com/Azure/autorest/tree/master/AutoRest/AutoRest.Core.Tests/Resource). I'm not 100% sure how it's used, but it seems it's needed to inform the tool about what is supports. Both JSON files need to be in your bin.
The serviceClient object is what you want. It will contain information about the methods, model types, method groups
Let me know if this works. You can try it with their resource files. I used their ExtensionLoaderTests for reference when I was playing around(https://github.com/Azure/autorest/blob/master/AutoRest/AutoRest.Core.Tests/ExtensionsLoaderTests.cs).
(Also thank you to the Denis, an author of AutoRest)
If still a question you can use Swagger Parser library:
https://github.com/swagger-api/swagger-parser
as simple as:
// parse a swagger description from the petstore and get the result
SwaggerParseResult result = new OpenAPIParser().readLocation("https://petstore3.swagger.io/api/v3/openapi.json", null, null);

App Engine Instance ID

Is it possible to get info on what instance you're running on? I want to output just a simple identifier for which instance the code is currently running on for logging purposes.
Since there is no language tag, and seeing your profile history, I assume you are using GAE/J?
In that case, the instance ID information is embedded in one of the environment attributes that you could get via ApiProxy.getCurrentEnvironment() method. You could then extract the instance id from the resulting map using key BackendService.INSTANCE_ID_ENV_ATTRIBUTE.
Even though the key is stored in BackendService, this approach will also work for frontend instances. So in summary, the following code would fetch the instance ID for you:
String tInstanceId = ApiProxy.getCurrentEnvironment()
.getAttributes()
.get( BackendService.INSTANCE_ID_ENV_ATTRIBUTE )
.toString();
Please keep in mind that this approach is quite undocumented by Google, and might subject to change without warning in the future. But since your use case is only for logging, I think it would be sufficient for now.
With the advent of Modules, you can get the current instance id in a more elegant way:
ModulesServiceFactory.getModulesService().getCurrentInstanceId()
Even better, you should wrap the call in a try catch so that it will work correctly locally too.
Import this
import com.google.appengine.api.modules.ModulesException;
import com.google.appengine.api.modules.ModulesServiceFactory;
Then your method can run this
String instanceId = "unknown";
try{
instanceId = ModulesServiceFactory.getModulesService().getCurrentInstanceId();
} catch (ModulesException e){
instanceId = e.getMessage();
}
Without the try catch, you will get some nasty errors when running locally.
I have found this super useful for debugging when using endpoints mixed with pub-sub and other bits to try to determine why some things work differently and to determine if it is related to new instances.
Not sure about before, but today in 2021 the system environment variable GAE_INSTANCE appears to contain the instance id:
instanceId = System.getenv("GAE_INSTANCE")

Resources