How to use pagination at api localbitcoin - api

I'm developing with localbitcoin API and i am using path “/api/dashboard/closed/” and this is my code:
<?php
function localbitcoinsquery($path, $nonce,array $req = Array()) {
global $random;
$key='mykey';
$secret='secretkey';
if ($req) {
$get=httpbuildquery($req);
$path=$path.'?'.$get;
}
$postdata=$nonce.$key.$path;
$sign = strtoupper(hashhmac('sha256', $postdata, $secret));
$headers = array(
'Apiauth-Signature:'.$sign,
'Apiauth-Key:'.$key,
'Apiauth-Nonce:'.$nonce
);
$ch = null;
$ch = curlinit('https://localbitcoins.com'.$path);
curlsetopt($ch, CURLOPTRETURNTRANSFER, true);
curlsetopt($ch, CURLOPTHTTPHEADER, $headers);
curlsetopt($ch, CURLOPTSSLVERIFYPEER, TRUE);
curlsetopt($ch, CURLOPTCONNECTTIMEOUT, 20);
$res = curlexec($ch);
if ($res === false) throw new Exception('Curl error: '.curlerror($ch));
$dec = jsondecode($res, true);
if (!$dec) throw new Exception('Invalid data: '.$res);
curl_close($ch);
return $dec;
}
$getinfo = array();
$url='/api/dashboard/closed/';
$mt = explode(' ', microtime());
$random = $mt[1].substr($mt[0], 2, 6);
$getinfo = localbitcoinsquery($url,$random);
echo "<pre>";
printr($getinfo);
echo "</pre>";
?>
This works OK, but show only 50 trades,
Also I get this at result:
[pagination] => Array
(
[next] => https://localbitcoins.com/api/dashboard/closed/?order_by=-closed_at&start_at=2017-10-26+17%3U50%3A49%2B00%9A00
)
But I don't know how to use pagination, when I try to use this link at my code I get error:
[message] => HMAC authentication key and signature was given, but they
are invalid. Error 41
I already investigated at google large time but the information is scarce.

I'm using the python library and had the same issue. When I spoke to technical support they said the issue was in the way I was calculating the authentication.
Basically you have to include the pagination url as part of the signature.
On the python library at least, you do not have to change the api endpoint since arguments are being delivered as part of the form data.
So you still access for example "/api/dashboard/closed/" when getting the second page and the "?order_by=-closed_at&start_at=2017-10-26+17%3U50%3A49%2B00%9A00" stuff goes in the form somehow.
The python API does all this for you, you just have to copy the example from the github page.

I fixed error no. 41. I modified your example to show that works, (read my NOTE: comments to understand better where is the problem) Read my NOTE: comments.
<?php
function localbitcoins_query($path, array $req = Array()) {
$key='yourkey';
$secret='yoursecret';
$array_mt = explode(' ', microtime());
$nonce = $array_mt[1].substr($array_mt[0], 2, 6);
$get = "";
if ($req) {
$get=http_build_query($req);
}
$postdata=$nonce.$key.$path.$get; // NOTE: here $postdata goes without '?' char before the parameters!
$sign = strtoupper(hash_hmac('sha256', $postdata, $secret));
$headers = array(
'Apiauth-Signature:'.$sign,
'Apiauth-Key:'.$key,
'Apiauth-Nonce:'.$nonce
);
$ch = null;
$ch = curl_init('https://localbitcoins.com'.$path.( $get=="" ? "" : "?".$get)); // NOTE: here it's necesary '?' char before the parameters!
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
$res = curl_exec($ch);
if ($res === false) throw new Exception('Curl error: '.curlerror($ch));
$dec = json_decode($res, true);
if (!$dec) throw new Exception('Invalid data: '.$res);
curl_close($ch);
return $dec;
}
$getinfo = array();
$api_endpoint = '/api/dashboard/closed/';
$array_params = array( "order_by" => "-closed_at"
, "start_at" => "2019-08-14 18:00:26+00:00"
);
$getinfo = localbitcoins_query($api_endpoint,$array_params);
echo "<pre>"; print_r($getinfo); echo "</pre>";
?

Related

Gate.io PHP API create order problem => Signature mismatch

I'm not an expert in API development or using signed messages in PHP.
I have however tried to get the GATE.IO v4 API working in my PHP implementation but keep getting "Signature mismatch". I have followed the API documentation for CREATE ORDER available at Gate.io's website here: https://www.gate.tv/docs/developers/apiv4/#create-an-order
I have managed to get the /spot/accounts working, so I know that the key and secret are correct.
Based on the code below I seem to missing something. Probably a tiny error but those are the hardest, right?
Does anyone have any idea what could be the cause of this issue? Would really appreciate your help after having spent 8+ hours trying to get this to work.
<?php
$accessToken = ''; // Access token for OAuth/Bearer authentication
$key = "XXXXXXXXXXXXXXXXXXXXXXX";
$secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$username = ''; // Username for HTTP basic authentication
$password = ''; // Password for HTTP basic authentication
$host = 'https://api.gateio.ws/api/v4'; // The host
$userAgent = 'OpenAPI-Generator/5.26.0/PHP'; // User agent of the HTTP request, set to "OpenAPI-Generator/{version}/PHP" by default
$sResourcePath = "/spot/orders";
$sMethod = "POST"; // POST or GET
$aPayload['currency_pair'] = "DOT_USDT";
$aPayload['price'] = "6.330033";
$aPayload['account'] = "spot";
$aPayload['side'] = "buy";
$aPayload['amount'] = "1";
$aPayload['time_in_force'] = "gtc";
$sBody = json_encode($aPayload);
$aQueryParams = $aPayload;
$aFullPath = parse_url($host . $sResourcePath);
$fullPath = $aFullPath['path'];
$timestamp = time();
$hashedPayload = hash("sha512", ($payload !== null) ? $payload : "");
$fmt = "%s\n%s\n%s\n%s\n%s";
$sQuery = http_build_query($aQueryParams, false);
$signatureString = sprintf($fmt, $sMethod, $fullPath, $sQuery, $hashedPayload, $timestamp);
$signature = hash_hmac("sha512", $signatureString, $secret);
$aSignHeaders = array(
"KEY" => $key,
"SIGN" => $signature,
"Timestamp" => $timestamp);
$aHeaders[] = "KEY: " . $aSignHeaders['KEY'];
$aHeaders[] = "SIGN: " . $aSignHeaders['SIGN'];
$aHeaders[] = "Timestamp: " . $aSignHeaders['Timestamp'];
$aExtraParams['sHttpHeaders'] = $aHeaders;
if ($sMethod == "POST")
{
$sParams = "?" . http_build_query($aQueryParams, false);
}
else
{
$sQuery = "";
}
$sSubmitUrl = $host . $sResourcePath . $sParams;
$sPage = CURL::doRequest($sMethod, $sSubmitUrl, $sParams, $aExtraParams);
$aPage = json_decode($sPage, true);
if ($aPage)
{
$iPage = count($aPage);
}
echo "<pre>";
print_r($aPage);
echo "</pre>";
?>
based on that example request, you should be doing something like this
//path & urls
$host = 'https://api.gateio.ws';
$prefix = '/api/v4';
$path = '/spot/orders';
$fullPath = "$prefix$path";
$method = 'POST';
//your API keys
$api = [
'secret' => 'xxxx'
];
// Your actual data you can easily modify
$payload = [
'currency_pair' => 'DOT_USDT',
'price' => '6.330033',
'account' => 'spot',
'side' => 'buy',
'amount' => '1',
'time_in_force' => 'gtc'
];
//Convert your data to JSON FORMAT
$jsonPayload = json_encode( $payload );
//Hash your JSON DATA
$hashJsonPayload = hash('sha512', $jsonPayload);
$timeStamp = time();
// dunno if this is required
$queryParam = '';
//Create your signature string
$signString="$method\n$fullPath\n$queryParam\n$hashJsonPayload\n$timeStamp";
//Generate the signature
$signHash = hash_hmac('sha512', $signString, $api['secret']);
// Your Actual headers
$headers = [
'Content-Type: application/json',
'Timestamp: '.$timeStamp,
'Key: '.$api['secret'],
'SIGN: '.$signHash
];
Example request using php curl
$ch = curl_init( "$host$fullPath" ); // URL to POST https://api.gateio.ws/api/v4/spot/orders
curl_setopt( $ch, CURLOPT_POSTFIELDS, $jsonPayload ); // set json payload as body here
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers ); //define header here
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$result = curl_exec($ch);
curl_close($ch)
echo '<pre>', print_r($result, 1), '</pre>';

Instagram basic display api withlaravel

I'm working on Instagram basic api, in my project user can connect their Instagram feed to our project. For that I'm generating a short live authentication code but could not get the long live access code. Its returning null.
Here is my code for getting long live access code.
$client_secret = "###############";
$client_id = "###############";
$redirect_uri = '#########';
$short_access_token = "####"; // getting this from another function
$ig_rtu = 'https://api.instagram.com/oauth/access_token?client_id='.$client_id.'&client_secret='.$client_secret.'&grant_type=authorization_code&redirect_uri='.$redirect_uri.'&access_token='.$short_access_token;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ig_rtu);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ig_new = curl_exec($ch);
curl_close ($ch);
return $ig_new = json_decode($ig_new, true);
In postman this works fine but I could not get it done in Laravel.
What I'm missing here ?
Any lead is appreciated.
I've done this in 3 steps. I will leave the code out for step 1 and include my implementation for step 2 and 3.
Steps:
get the code
get the short lived token using the code
get the long lived token using the short lived token
Here are the public variables used.
public $appId = null;
public $appSecret = null;
public $redirectUrl = null;
// Instagram request data
public $socialUserId = null;
public $socialAuthCode = null;
public $socialUserName = null;
public $socialShortAccessToken = null; // 1 hour
public $socialLongAccessToken = null; // 60 days
public $socialLongAccessTokenExpiresInSeconds = null; // 5183910 seconds || 59.99896 days - relative to date created
Step 2:
public function getUserIdAndShortAccessToken(){
/* Get UserId and access Token
https://api.instagram.com/oauth/access_token \
-F client_id={app-id} \
-F client_secret={app-secret} \
-F grant_type=authorization_code \
-F redirect_uri={redirect-uri} \
-F code={code}
*/
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,
'https://api.instagram.com/oauth/access_token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$post = array(
'client_id' => $this->appId,
'client_secret' => $this->appSecret,
'grant_type' => 'authorization_code',
'redirect_uri' => $this->redirectUrl,
'code' => $this->socialAuthCode,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$curlResult = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
curl_close($ch);
return;
}else{
curl_close($ch);
}
$this->socialUserId = json_decode($curlResult)->user_id;
$this->socialShortAccessToken = json_decode($curlResult)->access_token;
}
Step 3:
public function getLongAccessToken(){
/* Get long-lived token
curl -i -X GET "https://graph.instagram.com/access_token
?grant_type=ig_exchange_token
&client_secret={instagram-app-secret}
&access_token={short-lived-access-token}"
*/
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'https://graph.instagram.com/access_token?grant_type=ig_exchange_token&client_secret='
.$this->appSecret.'&access_token='
.$this->socialShortAccessToken
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$curlResult = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
curl_close($ch);
return;
}else{
curl_close($ch);
}
$this->socialLongAccessToken = json_decode($curlResult)->access_token;
$this->socialLongAccessTokenExpiresInSecond = json_decode($curlResult)->expires_in;
}

How to make separate config file for sms sending

I have done a sms sending code in codeigniter. It is worked successfully. But actually i want to make a config file so that i will not write the username, password, senderid on each page.
Here is my code below. First i have done a library file for sms sending.
Sms.php
<?php
class SMS
{
function SendSMS($url)
{
if(function_exists('curl_init'))
{
$ch = curl_init();
$timeout = 60;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT,$timeout);
$data = curl_exec($ch);
if($data === FALSE){
throw new Exception(curl_errno($ch));
}
curl_close($ch);
return $data;
}
else
{
return false;
}
}
}
?>
Again for sms sending i am writting code in each controller something like this.
$sms_username = "GAPSMS";
$sms_password = "GAPSMS";
$sms_senderid = "GAPSMS";
$sms_mobile = $mobile;
$sms_message = urlencode('Your One Time Password for transaction is: '.$otp);
$sms_api = "http://sendsms.sandeshwala.com/API/WebSMS/Http/v1.0a/index.php?username=$sms_username&password=$sms_password&sender=$sms_senderid&to=$sms_mobile&message=$sms_message&reqid=1&format={json|text}";
$this->sms->SendSMS($sms_api);
This much below code i want to write in a config file in such a way so that i can write this once and then can use in every controller to send sms.
$sms_username = "GAPSMS";
$sms_password = "GAPSMS";
$sms_senderid = "GAPSMS";
UPDATED
In CodeIgniter, libraries can have their own configuration file. Let's change your library a bit:
<?php
class Sms
{
private $_username = 'GAPSMS'; // default value
private $_password = 'GAPSMS'; // default value
private $_senderid = 'GAPSMS'; // default value
/**
* Class constructor so the config
* file is loaded.
*/
public function __construct($config = array())
{
if ( ! empty($config))
{
foreach ($config as $key => $val)
{
$this->{"_".$key} = $val;
}
}
}
function send($mobile, $message)
{
if(function_exists('curl_init'))
{
$url = 'http://sendsms.sandeshwala.com/API/WebSMS/Http/v1.0a/index.php?username='.$this->_username.'&password='.$this->_password.'&sender='.$this->_senderid.'&to='.$mobile.'&message='.$message.'&reqid=1&format={json|text}';
$ch = curl_init();
$timeout = 60;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT,$timeout);
$data = curl_exec($ch);
if($data === FALSE){
throw new Exception(curl_errno($ch));
}
curl_close($ch);
return $data;
}
else
{
return false;
}
}
}
Then go create the config file application/config/sms.php inside which you put:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$config['username'] = 'GAPSMS';
$config['password'] = 'GAPSMS';
$config['senderid'] = 'GAPSMS';
// End of file.
Now whenever the library is loaded, and config file is loaded as well as values are set, everything should work just fine. And the rest of the code would be:
// Load the library and simply pass mobile number and message.
$this->load->library('sms');
$data = $this->sms->send('0123456789', 'Hello, this is the message');

Send XML via Put with CakePHP

I want to send a put request to an API which wants the details of the request as XML
Apparently I need to send the xml as a file when using PUT with PHP.
How can I do this?
Here is what I'm trying:
$HttpSocket = new HttpSocket();
$result = $HttpSocket->put($put, $fh);
where $put is the url and $fh is a file i have made on the fly like this
$xmlObject = Xml::fromArray($xmlArray);
$xmlString = $xmlObject->asXML();
$fh = fopen('php://memory', 'rw');
fwrite($fh, $xmlString);
rewind($fh);
I've tested it on cake 2.0.5, and HttpSocket::put can send key-value arrays or raw strings as postdata.
So, you can send the xml string directly, and the remote server will read it in Raw Post Data i. e. file_get_contents("php://input")
This works:
$http = new HttpSocket();
$xml_data = Xml::fromArray($data);
$xml_string = $xml_data->asXML();
$response = $http->put('http://example.com', $xml_string);
To demonstrate it, I've created a Controller called RequestXmlTestController filed under 'Controllers/RequestXmlTestController.php' (code is below), and an empty view filed under 'RequestXmlTests/index.ctp'
Controller code:
<?php
App::uses('AppController', 'Controller');
/**
* RequestXmlTest Controller
*
*/
class RequestXmlTestController extends AppController {
/**
* Use no Model
*/
public $uses = array();
/**
* index action
*/
public function index(){
App::uses('HttpSocket', 'Network/Http');
App::uses('Xml', 'Utility');
$http = new HttpSocket();
$data = array(
'type' => array('name' => 'Campaign', 'data' => array(
array('name' => 'Come eat at Joe\'s', 'products' => array('adserver', 'analytics'))
))
);
$xml_data = Xml::fromArray($data);
$xml_string = $xml_data->asXML();
$response = $http->put(Router::url(array('action' => 'test'), true), $xml_string);
debug($response);
}
/**
* test action
* Test the requests and dump Raw Post Data and Cake's Request object
*/
public function test(){
var_dump(array('raw_post_data' => file_get_contents("php://input")));
echo "\n\n";
var_dump($this->request);
exit;
$this->render('index');
}
}
References:
HttpSocket Documentation
I ended up doing this just using php rather than the php helpers
# write data into a temporary file
$putData = "<subscription><productPath>$new_product_path</productPath></subscription>";
$putDataFile = tmpfile();
fwrite($putDataFile, "<subscription><productPath>$new_product_path</productPath></subscription>");
fseek($putDataFile, 0);
# initialize PUT call
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://api.example.com");
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/xml"));
curl_setopt($ch, CURLOPT_INFILE, $putDataFile);
curl_setopt($ch, CURLOPT_INFILESIZE, strlen($putData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
# executes PUT call and clean up
$result = curl_exec($ch);
$info = curl_getinfo($ch);
fclose($putDataFile);
curl_close($ch);
I'd have preferred using the Cake classes for neatness, but this works with the api i was using.

Facebook API call- "This API version is deprecated"

I'm trying to call to Photo.upload on the the Facebook API server. As far as I can tell the code to construct the call is good but I can't understand the responce I'm getting back from the server. As far as I can see, this call is ment to work and other people don't get this problem. I can only reason that something is wrong with the code. The commented stuff is an artifact of me trying different things to get a different responce from the server. The original code that I've changed was in part taken from an example of how to do this which I couldn't get to work either really:
http://www.jaisenmathai.com/blog/2008/11/27/using-the-facebook-api-to-upload-photos/
Server Responce:
12 This API version is deprecated method photos.upload api_key b92cee19a33c861275bfce4695896e44 call_id 1250194789.61 garden_jpg /var/www/vivaladan/pictureyourselfhull/garden.jpg v 0 sig 896ee95339cad24ce7e64a05ca764123
Code:
$key = b92cee19a33c861275bfce4695896e44;
$ver = 1.0;
$cid = microtime(true);
$uid = BIGINT;
$file= "garden.jpg";
$args = array(
//amethod => photos.upload,
v => $ver,
api_key => $key,
//uid => $uid,
call_id => $cid,
//format => XML
);
$args[basename($file)] = realpath($file);
signRequest($args,$sec);
$postString = "";
foreach($args as $index => $value) {
$postString .= $index ."=".$value."&";
}
$postString = trim($postString, '&');
$ch = curl_init();
$url = "http://api.facebook.com/restserver.php?method=photos.upload";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
$data = curl_exec($ch);
echo $data;
function signRequest(&$args, $secret){
ksort($args);
$sig = "";
foreach($args as $k => $v){
$sig .= $k . '=' . $v;
}
$sig .= $secret;
$args[sig] = md5($sig);
}
Rest API call is not working anymore.
Try GraphApi
I'm guessing it's because you're using $ver = 0.0; - there's no 0.0 version of the API.
try using api.new.facebook.com API URL instead