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 :)
Related
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.
What I have is private key without header, footer and spaces (it's test one)
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg0m4yLz+sdzZtBG9Q3HQ9++wcfq1O4hOWgSBMb/A6eijyhRANCAAQeB0fBl2D7HZOKVBjpPiU2jabzNxQU4ZYrJ+MSA3LpzZxmRk2JaFHNujjkJghQT19HHjg3Fnkb8Y9oIhB9neXBI
And this code in android which generates signature in required format.
val signatureSHA256 = Signature.getInstance("SHA256withECDSA")
val encoded = Base64.decode(privateKeyHere, Base64.DEFAULT)
val privateKey: PrivateKey = KeyFactory.getInstance("EC").generatePrivate(PKCS8EncodedKeySpec(encoded))
signatureSHA256.initSign(privateKey)
val finalSignature = signatureSHA256.sign().toHexString()
//Somewhere
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
And function which return timestamp:
fun getXTimestamp(): Long {
return (System.currentTimeMillis() / 1000L)
}
From android Im getting finalSignature and getXTimestamp()
And I need to verify my signature in php script:
$timestamp = '1625730735';
$public_key = "
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHgdHwZdg+x2TilQY6T4lNo2m8zcU
FGWKyfjEgNy6c2cZkZNiWhRzbo45CYIUE9fRx44NxZ5G/GPaCIQfZ3lwSA==
-----END PUBLIC KEY-----
";
//hex2bin("finalSignature")
$sign = hex2bin("3045022048011d511094a5270c528ca5064b07084e36ccfd2ee3f5e1e20278fb5d83cdba022100d71a0096ef2c6288554a51017a89374b18c7e84ba7031a43d67f53d7ce89152c");
$result = openssl_verify($timestamp, $sign, $public_key, OPENSSL_ALGO_SHA256);
print $result;
Now php script launched from console returns 0 but should return 1.
I think I should somehow update or put timestamp in signature.
I tried to put it in update() as bytes, but still got 0
Who can help pls?)
On PHP side ("verification") you use your 'timestamp' as text string as input for your openssl_verify function.
On Kotlin-side you need to do the same - get the timestamp as string and use it as input for a sign.update call with [Pseudo-code] timestamp-string.getBytes(StandardCharset.UTF8) as input.
As I'm not familiar with Kotlin I'm using the code in the comment of #Andrej Kijonok as it solves the problem :-)
val signatureTimestamp = getXTimestamp().toString().toByteArray(Charsets.UTF_8)
signatureSHA256.initSign(privateKey)
signatureSHA256.update(signatureTimestamp)
I have this code on Android:
val digest = MessageDigest.getInstance("SHA-512")
digest.update("secretotpkey".toByteArray())
val sb = StringBuilder()
val bytes = digest.digest(value.toByteArray())
bytes.forEach {
sb.append(((it and 0xF) + 0x100).toString(16).substring(1))
}
val encryptedValue = sb.toString()
makeLog("Encrypted value is $encryptedValue")
return encryptedValue
I am trying to convert this to iOS by using CryptoSwift. However I am getting different results. Any ideas how to fix?
var digest = Digest.sha512("secretotpkey".bytes)
print(digest)
let bytes = "54181474".bytes
print(bytes)
digest.append(contentsOf: bytes)
var blah = String()
for item in digest {
let a = Int(item & 0xF) + Int(0x100)
let b = (String(format:"%02X", a)).substring(range: NSRange(location: 1, length: 2))
print(b)
blah.append(b)
}
Two encoding issues:
you're not indicating the characters set when converting the key to bytes (a key should consist of bytes in the first place, strings are not keys).
your hex encoding is clearly not correct for either Kotlin or Swift; please use a pre-made library call instead or look up correct code here on StackOverflow.
That should fix it, because there is nothing there but a call to a standardized algorithm, SHA-512 otherwise.
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.
is there a way to query the play store for the version of an app without the need for user-credentials. I am aware of this unofficial API:
http://code.google.com/p/android-market-api/
but I don't want to rely on user credentials - I can visit the google play sites in incognito mode via chrome also - so it must be possible somehow. But I found no way and I don't want to fallback on scraping ;-)
Found a suitable API via G+:
this is the API: https://androidquery.appspot.com
example call: https://androidquery.appspot.com/api/market?app=org.ligi.fast
and this wrapper/code: https://github.com/androidquery/androidquery
Also check out: www.playstoreapi.com
It's unofficial but easy to use (free for non commercial use). you can get data about apps, search the play store and get top charts data. from their documentation section:
Node.js:
var request = require('request');
var apiKey = 'wij5czxu3mxkzkt9'; // your API key
var packageName = 'com.whatsapp'; // package Name, e.g. com.whatsapp for WhatsApp
var url = 'http://api.playstoreapi.com/v1.1/apps/' + packageName + '?key=' + apiKey;
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body) // Print the json response
}
});
HTML/JS:
<html>
<head>
<body>
<p></p>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
var apiKey = 'wij5czxu3mxkzkt9'; // your API key
var app = 'com.whatsapp'; // package com.whatsapp for WhatsApp
var url = 'http://api.playstoreapi.com/v1.1/apps/' + app + '?key=' + apiKey;
$.getJSON(url).done(function(appDetails) {
$('p:last').html(JSON.stringify(appDetails));
});
</script>
</body>
</head>
<html>
Python:
import urllib2
import json
packageName = 'com.whatsapp' # package com.whatsapp for WhatsApp
apiKey = 'wij5czxu3mxkzkt9' # your API key
url = 'http://api.playstoreapi.com/v1.1/apps/{0}?key={1}'
response = urllib2.urlopen(url.format(packageName, apiKey))
data = json.load(response)
print data
C# .NET:
string apiKey = "wij5czxu3mxkzkt9"; // your API key
string app = "com.whatsapp"; // package com.whatsapp for WhatsApp
string url = "http://api.playstoreapi.com/v1.1/apps/{0}?key={1}";
using (var webClient = new System.Net.WebClient()) {
string jsonString = webClient.DownloadString(string.Format(url, app, apiKey));
}
Bear in mind that nowadays a lot of apps have multiple versions running. For those apps with one version you can try 42matters Lookup API, it should give you the correct version.