Citrus iOS Integration: Invalid signature key - android

I am using citrus Payments for payment using credit card in iOS. I have generated a bill from my server and am creating a CTSBill using merchant transaction id, amount, request signature, merchant access key, return url and notify url. I am then passing this to requestChargePayment method, but I get an error Invalid signature key.
let creditCard = CTSElectronicCardUpdate(creditCard: ())
creditCard.number = "5555555555554444" //test card
creditCard.expiryDate = "12/2017"
creditCard.scheme =
creditCard.ownerName = "Anna"
creditCard.cvv = 132 //Dummy one
let paymentInfo : CTSPaymentDetailUpdate = CTSPaymentDetailUpdate()
paymentInfo.addCard(creditCard)
PaymentUtil.sharedInstance.paymentLayer.requestChargePayment(paymentInfo, withContact: self.getContactInfo(), withAddress: self.getAddressInfo(), bill: bill, customParams: nil, returnViewController: self, withCompletionHandler: { (cashRes, error) -> Void in
//error
})
I get the following error in the block:
Error Domain=com.citrus.errorDomain Code=383066336 "Invalid signature key" UserInfo=0x16b57490 {NSLocalizedDescription=Invalid signature key}
The same parameters work for android and I have verified the keys I have been using but not sure what am I doing wrong.

Related

Public key credential verification using android biometric for StrongKeyFido2 API

I am creating an app that works like an authenticator for the website logins, I have setup a server of https://www.strongkey.com/ and here is the samples I am following https://github.com/StrongKey/fido2/tree/master/sampleapps/java/sacl/mobile/android.
But I am not aware how to achieve this facility, What my application is doing is
Hitting the pre register api and getting the challenge to register
sample response
{"Response":{"rp":{"name":"FIDOServer","id":"fidoidqa.com"},"user":{"name":"devendra","id":"s5wXaholuoVwk86KQ0d_hmIxOkQPNS-bBBes8X4Cex8","displayName":"devendraLiapC"},"challenge":"COJ03Ch_6KDjlvnZ1jg_Qw","pubKeyCredParams":[{"type":"public-key","alg":-7},{"type":"public-key","alg":-35},{"type":"public-key","alg":-36},{"type":"public-key","alg":-8},{"type":"public-key","alg":-47},{"type":"public-key","alg":-257},{"type":"public-key","alg":-258},{"type":"public-key","alg":-259},{"type":"public-key","alg":-37},{"type":"public-key","alg":-38},{"type":"public-key","alg":-38}],"excludeCredentials":[{"type":"public-key","id":"NEVDOUQzNkMzMDBEM0U3MS1FNDczNTQ3QUVDRDQ1ODDRELTk1MEJFOTM2NTI5MEIxNjctMTIxNkNFQjY1ODIzQTI5OQ","alg":-7},{"type":"public-key","id":"MUUzMDY0RkNGQUZEOTM5Ni1FMzlFOUM2MkUwOTQE4NzcwLTA0NzUyMEFBREM0ODUwM0UtMEU4ODdFOEFCRjFCMDE3QQ","alg":-7},{"type":"public-key","id":"hhkXnYmUiu_bzLy5HPHJvZs6TQA-302jRdeLHBgpL40","alg":-257}],"attestation":"direct"}}
Then with this response, I am creating the preregisterchallenge,
var preregisterChallenge = PreregisterChallenge() val authenticatorSelectionCriteria = AuthenticatorSelectionCriteria() authenticatorSelectionCriteria.authenticatorAttachment = "Android" authenticatorSelectionCriteria.isRequireResidentKey = true authenticatorSelectionCriteria.userVerification = "required" val authSelectionJson = Gson().toJson(authenticatorSelectionCriteria) val myCustomArray: JsonArray = Gson().toJsonTree(userData.Response?.pubKeyCredParams).asJsonArray preregisterChallenge.apply { id = 100 uid = 1001 did = 1003 rpid = userData.Response?.rp?.id userid = "1001" username = "devendra" displayName = "devendra" challenge = userData.Response?.challenge authenticatorSelectionJSONObject = JSONObject(authSelectionJson) authenticatorSelection = authSelectionJson publicKeyCredentialParams = myCustomArray.toString() credParamsJSONArray = JSONArray(myCustomArray.toString()) }
And then doing like this
val publicKeyCredential = AuthenticatorMakeCredential.execute( ContextWrapper(context), preregisterChallenge, "fidoidqa.com" ) as PublicKeyCredential
I am getting the publickKeyCredential without any error
Now I want to attest this key with biometric humen presence with this public key, for example now user will touch the biometric to verify this public key and then I will call the register api.
How can I attest the public key credential with the biometric fingerprint and want a signed public key credential for future verification.
Hope this is well explained, Please help me in understanding the flow or process.
Thanks in advance

Google Cloud TextToSpeech : java.io.IOException: The Application Default Credentials are not available

I am trying to run the TextToSpeech code from Google Cloud TextToSpeech Service.
Curently stuck at Authentication part referring link Authenticating as a service account
Below is the Code :
public class TexttoSpeech {
/** Demonstrates using the Text-to-Speech API. */
public static void getAudio() throws Exception {
// Instantiates a client
// Below Line is Point of Error in Code
try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
// Set the text input to be synthesized
SynthesisInput input = SynthesisInput.newBuilder().setText("Hello, World!").build();
// Build the voice request, select the language code ("en-US") and the ssml voice
//gender
// ("neutral")
VoiceSelectionParams voice =
VoiceSelectionParams.newBuilder()
.setLanguageCode("en-US")
.setSsmlGender(SsmlVoiceGender.NEUTRAL)
.build();
// Select the type of audio file you want returned
AudioConfig audioConfig =
AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();
// Perform the text-to-speech request on the text input with the selected voice parameters and
// audio file type
SynthesizeSpeechResponse response =
textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);
// Get the audio contents from the response
ByteString audioContents = response.getAudioContent();
byte[] audioArray=audioContents.toByteArray();
String converted= Base64.encodeBase64String(audioArray);
playAudio(converted);
// Write the response to the output file.
try (OutputStream out = new FileOutputStream("output.mp3")) {
out.write(audioContents.toByteArray());
System.out.println("Audio content written to file \"output.mp3\"");
}
}
}
public static void playAudio(String base64EncodedString){
try
{
String url = "data:audio/mp3;base64,"+base64EncodedString;
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
}
}
But getting below error on :
java.io.IOException: The Application Default Credentials are not available. They are available
if running in Google Compute Engine. Otherwise, the environment variable
GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials.
See https://developers.google.com/accounts/docs/application-default-credentials for more
information.
Also tried Explicit credentials :
#Throws(IOException::class)
fun authExplicit() {
val projectID = "texttospeech-12345" // dummy id
// val imageUri: Uri =
Uri.fromFile(File("file:\\android_asset\\service_account_file.json"))
// val path=File(imageUri.path).absolutePath
// You can specify a credential file by providing a path to GoogleCredentials.
// Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment
variable.
val credentials =
GoogleCredentials.fromStream(mContext.resources.openRawResource(R.raw.service_account_file))
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"))
val storage: Storage =
StorageOptions.newBuilder().setProjectId(projectID).setCredentials(credentials)
.build().service
println("Buckets:")
// Error at storage.lists()
val buckets: Page<Bucket> = storage.list()
for (bucket in buckets.iterateAll()) {
println(bucket.toString())
}
}
But on device it gives error like :
Error getting access token for service account:
Unable to resolve host "oauth2.googleapis.com": No address associated with hostname, iss:
xyz#texttospeech-12345.iam.serviceaccount.com
And on Emulator the error is :
xxxxxxxxx does not have storage.buckets.list access to the Google Cloud project.
Please let me know if you guys need something more.
Any suggestion will be appreciated
Thanks in Advance
Also if I run below command in Cloud SDK :
gcloud auth application-default login
I get this but I didnt understood what its trying to say
You can pass the credentials while creating the client connection.
TextToSpeechSettings settings = TextToSpeechSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(authExplicit("JSON FILE PATH")))
.build();
try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create(settings)) {
// ... rest of your code
}
// ... rest of your code
And
public static GoogleCredentials authExplicit(String jsonPath) throws IOException {
GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(jsonPath))
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
return credentials;
}
GoogleCredentials imported from Google Auth Library For Java OAuth2 HTTP
N.B You need to make sure you are able to fetch the JSON file in your application.

How to obtain a p12 file (key.p12) from Google Cloud?

I need to download my key.p12 file from https://console.cloud.google.com/ but I dont know how to do it now.
My Dashboard "Api & Services > Credentials" is like this:
I need this p12 file to connect to the PHP API Google_Service_AndroidPublisher with this code (I am using the same code in this Stackoverflow answer to the question Get android subscription status, failed with 403:
$service_account_name = 'testing#nootrictesting.iam.gserviceaccount.com'; //Your service account email
$key_file_location = ''; // p12 file (key.p12)
$client = new Google_Client();
$client->setApplicationName("My name app"); //This is the name of the linked application
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/androidpublisher'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$apiKey = ""; //API key
$client->setDeveloperKey($apiKey);
$service = new Google_Service_AndroidPublisher($client);
$results = $service->purchases_subscriptions->get("MY_ANDROID_APP_PACKAGE", $product_id, $purchase_token, array());
Any help will be useful.
Thanks!!!
DalmoTo linked the video in their comment that shows how/where to grab keys: youtu.be/asrCdWFrF0A?t=76
However, Google_Auth_AssertionCredentials looks like it shouldn't be used any longer (https://github.com/googleapis/google-api-php-client/blob/master/UPGRADING.md). Instead, use $client->setAuthConfig('/path/to/service-account.json'). Then you can use the json key file, not the p12 key file.

How To Send timeStamp and md5 hash for Marvel Api request

I'm trying to run a call to Marvel Api however the return I'm having is code = 401 Unauthorized, this is due to not being able to send the timeStamp and hash parameters correctly.
the url base is http://gateway.marvel.com/v1/public/ -> my url is being: = http: //gateway.marvel.com/ v1 / public / characters? name = wolverine & apikey = XXX & ts = 2019-04-06% 2013: 09: 10.272 & hash = [B # afad7ce8]
In the documentation it is described that I need to send these parameters:
Params: {
   "apikey": "your api key",
   "ts": "a timestamp",
   "hash": "your hash"
}
I need help to generate the ts and hash correctly.
Note: hash = ts + apiKey + publicKey
var ts = Timestamp(System.currentTimeMillis())
var hash = getHash(ts.toString())
fun getHash(ts: String): ByteArray? {
val byte = ts.toByteArray() + API_KEY.toByteArray() + PUBLIC_KEY.toByteArray()
val md = MessageDigest.getInstance("MD5")
return md.digest(byte)
}
You should not put your private key in code (it's bad practice and usually with this key you can do CRUD operations with API and even drop some parts of database).
Get your Marvel public key (for example 1234), your private key(for example abcd) and choose timestamp (for example 1564731162583).
Go to website https://passwordsgenerator.net/md5-hash-generator/
put your strings like 1564731162583abcd1234 (timestamp + private key + api key without spaces). You will get (with parameters from example) hash: B5936DEBCC1A252C679D2D3E5361B6C0
One more important thing: when you add this hash in your api call, timestamp have to be the same as in hash (previously chosen example 1564731162583) and also MD5 hash have to be in lowercase. This is important.
Hope it will help :)

Google Play Android Developer API from C#/.NET service - (400) Bad Request

I'm trying to access a Purchase Status API from my ASP.NET web server using Google APIs .NET Client Library which is a recommended way for using Purchase API v1.1. However, the Authorization page of this API suggests direct web requests to Google's OAuth2 pages instead of using the corresponding client libraries.
OK, I tried both methods with all variations I could imagine and both of them lead to "The remote server returned an error: (400) Bad Request.".
Now what I've done to get to my point. First I've made all steps 1-8 under the Creating an APIs Console project of the Authorization page. Next I generated a refresh token as described there. During refresh token generation I chose the same Google account as I used to publish my Android application (which is in published beta state now).
Next I've created a console C# application for test purposes in Visual Studio (may be console app is the problem?)
and tried to call the Purchase API using this code (found in some Google API examples):
private static void Main(string[] args)
{
var provider =
new WebServerClient(GoogleAuthenticationServer.Description)
{
ClientIdentifier = "91....751.apps.googleusercontent.com",
ClientSecret = "wRT0Kf_b....ow"
};
var auth = new OAuth2Authenticator<WebServerClient>(
provider, GetAuthorization);
var service = new AndroidPublisherService(
new BaseClientService.Initializer()
{
Authenticator = auth,
ApplicationName = APP_NAME
});
var request = service.Inapppurchases.Get(
PACKAGE_NAME, PRODUCT_ID, PURCHASE_TOKEN);
var purchaseState = request.Execute();
Console.WriteLine(JsonConvert.SerializeObject(purchaseState));
}
private static IAuthorizationState GetAuthorization(WebServerClient client)
{
IAuthorizationState state =
new AuthorizationState(
new[] {"https://www.googleapis.com/auth/androidpublisher"})
{
RefreshToken = "4/lWX1B3nU0_Ya....gAI"
};
// below is my redirect URI which I used to get a refresh token
// I tried with and without this statement
state.Callback = new Uri("https://XXXXX.com/oauth2callback/");
client.RefreshToken(state); // <-- Here we have (400) Bad request
return state;
}
Then I tried this code to get the access token (I found it here: Google Calendar API - Bad Request (400) Trying To Swap Code For Access Token):
public static string GetAccessToken()
{
var request = WebRequest.Create(
"https://accounts.google.com/o/oauth2/token");
request.Method = "POST";
var postData =
string.Format(
#"code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code",
// refresh token I got from browser
// also tried with Url encoded value
// 4%2FlWX1B3nU0_Yax....gAI
"4/lWX1B3nU0_Yax....gAI",
// ClientID from Google APIs Console
"919....1.apps.googleusercontent.com",
// Client secret from Google APIs Console
"wRT0Kf_bE....w",
// redirect URI from Google APIs Console
// also tried Url encoded value
// https%3A%2F%2FXXXXX.com%2Foauth2callback%2F
"https://XXXXX.com/oauth2callback/");
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
using (var dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
}
try
{
// request.GetResponse() --> (400) Bad request again!
using (var response = request.GetResponse())
{
using (var dataStream = response.GetResponseStream())
{
using (var reader = new StreamReader(dataStream))
{
var responseFromServer = reader.ReadToEnd();
var jsonResponse = JsonConvert.DeserializeObject<OAuth2Response>(responseFromServer);
return jsonResponse.access_token;
}
}
}
}
catch (Exception ex) { var x = ex; }
return null;
}
So, to sum up all my long story:
Is it possible at all to pass OAuth2 authorization using either of methods above from a C# Console Application (without user interaction)?
I've double checked the redirect URI (since I saw a lot of discussed troubles because of it here on stackoverflow) and other parameters like ClientID and ClientSecret. What else I could do wrong in the code above?
Do I need to URL encode a slash in the refresh token (I saw that the first method using client library does it)?
What is the recommended way of achieving my final goal (Purchase API access from ASP.NET web server)?
I'll try to answer your last question. If you access your own data account, you dont need to use client id in oAuth2. Let's use service account to access Google Play API.
Create a service account in Google Developer Console > Your project > APIs and auth > Credentials > Create a new key. You will download a p12 key.
Create a C# project. You can choose console application.
Install google play api library from Google.Apis.androidpublisher. Nuget. You can find other library for dotnet in Google APIs Client Library for .NET
Link google api project with your google play account in API access
Authenticate and try to query information. I'll try with listing all inapp item. You can just change to get purchase's status
String serviceAccountEmail = "your-mail-in-developer-console#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"physical-path-to-your-key\key.p12", "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { "https://www.googleapis.com/auth/androidpublisher" }
}.FromCertificate(certificate));
var service = new AndroidPublisherService(
new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "GooglePlay API Sample",
});
// try catch this function because if you input wrong params ( wrong token) google will return error.
var request = service.Inappproducts.List("your-package-name");
var purchaseState = request.Execute();
// var request = service.Purchases.Products.Get(
//"your-package-name", "your-inapp-item-id", "purchase-token"); get purchase'status
Console.WriteLine(JsonConvert.SerializeObject(purchaseState));
You should do the following in your
private static IAuthorizationState GetAuthorization(WebServerClient client) method:
private IAuthorizationState GetAuthorization(WebServerClient client)
{
IAuthorizationState state = AuthState;
if (state != null)
{
return state;
}
state = new AuthorizationState()
{
RefreshToken = "4/lWX1B3nU0_Ya....gAI",
Callback = new Uri(#"https://XXXXX.com/oauth2callback/")
};
client.RefreshToken(state);
// Store and return the credentials.
HttpContext.Current.Session["AUTH_STATE"] = _state = state;
return state;
}
Let me know if it works for you.
Be aware that we know that the whole OAuth2 flow is awkward today, and we are working to improve it.

Categories

Resources