invalid signature when attempting a sell - coinbase-api

I'm try to sell my bitcoin through the API from a specific wallet.
I have the GET calls working correctly, but the POST call is showing "invalid signature"
$API_KEY = '*****';
$API_SECRET = '*****';
$data['amount'] = 10;
$data['currency'] = 'USD';
$data['quote'] = true;
$api_url = '/v2/accounts/593b0285-****-****-****-f0ddcb6c9ccc/sells';
$timestamp = time();
$signature = hash_hmac('SHA256',$timestamp.'POST'.$api_url.json_encode($data),$API_SECRET;
$version = '2017-11-11';
$headers = array('CB-ACCESS-SIGN: '.$signature,
'CB-ACCESS-TIMESTAMP: '.$timestamp,
'CB-ACCESS-KEY: '.$API_KEY,
'CB-VERSION: '.$version);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.coinbase.com'.$api_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$data = curl_exec($ch);
This is the result I get from Coinbase
stdClass Object
(
[errors] => Array
(
[0] => stdClass Object
(
[id] => authentication_error
[message] => invalid signature
)
)
)
I've changed the currency to BTC to try that.
The account id in the $api_url is the one from when I perform an account API call.
[id] => 593b0285-****-****-****-f0ddcb6c9ccc
[name] => BTC Wallet
[primary] => 1
[type] => wallet

I figured it out, I was missing the Content-Type from my header.
$headers = array('CB-ACCESS-SIGN: '.$signature,
'CB-ACCESS-TIMESTAMP: '.$timestamp,
'CB-ACCESS-KEY: '.$API_KEY,
'CB-VERSION: '.$version,
"Content-Type: application/json");
It all works correctly now

Related

Capture data from CSV file contain variable for API request to save in new CSV file

I need the tracking number and order number when every line of Unique ID send the API request to the URL, and capture it to save in the new CSV file altogether with the API response.I really need help for this :/
packet.csv (CSV file contains variable for API request)
- Tracking #,Order #,Unique ID
- AB74832493,0dajKDhsa,478324
- CD78437294,kDHIdsan98,768542
track.csv (API response)
delivered,"2020-04-21 13:10:12"
delivered,"2020-02-29 12:55:51"
delivered,"2020-04-21 12:42:16"
desired track.csv (API response) :
Tracking #,Order#,Status,Date ((get the tracking and order from packet.csv)
0CS7lPuyKzO6,YT2010421266182766,delivered,"2020-04-21 13:10:12"
327231739327,YT7328729173217832,delivered,"2020-02-29 12:55:51"
743287493274,YT7438749327489324,delivered,"2020-04-21 12:42:16"
Controller :
public function getstatusbyid()
{
$csv_file = file('C:\wamp64\www\tetsing\application\csv\packet.csv');
$csv_data = [];
foreach ($csv_file as $line) {
$csv_data[] = str_getcsv($line);
}
$order_no = json_encode(array_column($csv_data, '0'));
$tracking = json_encode(array_column($csv_data, '1'));
$unique_id = array_column($csv_data, '2');
$access_key = 'SOMETHING';
if (FALSE === ($fp = fopen('C:\wamp64\www\testing\application\csv\track.csv', 'w'))) {
die("Error opening CSV file."); // TO DO: handle this better
}
foreach ($unique_id as $i => $id) {
$url = "https://track.my/api/getstatusbyid/$id";
$data = array(
'unique_id' => $id,
'access_key' => $access_key
);
$data_string = json_encode($data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 120);
$result = curl_exec($curl);
curl_close($curl);
$resultinfo = json_decode($result, true);
echo '<pre>';
print_r($resultinfo);
$status = $resultinfo["status"];
$date = $resultinfo["last_action_date_time"];
$resultdata = array();
$resultdata[] = array(
'status' => $status,
'date' => $date
);
if ($status == 'delivered') {
foreach ($resultdata as $fields) {
fputcsv($fp, $fields);
}
}
}
fclose($fp);
}
See this updated code, with comments to describe what's happening. Basically, you need to loop through each line in packet.csv, make the appropriate cURL call, and output the results:
public function getstatusbyid()
{
$access_key = 'SOMETHING';
$url = "https://track.my/api/getstatusbyid/$id";
if (FALSE === ($fp = fopen('C:\wamp64\www\testing\application\csv\track.csv', 'w'))) {
die("Error opening CSV file."); // TO DO: handle this better
}
$csv_file = file('C:\wamp64\www\tetsing\application\csv\packet.csv');
// Loop through each line in packet.csv:
foreach ($csv_file as $line) {
$csv_data = str_getcsv($line); // Get the next line
list( $order_no, $tracking, $id ) = $csv_data; // Split it up
$data = array(
'unique_id' => $id,
'access_key' => $access_key
);
$data_string = json_encode($data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 120);
$result = curl_exec($curl);
curl_close($curl);
$resultinfo = json_decode($result, true);
echo '<pre>';
print_r($resultinfo);
$status = $resultinfo["status"];
$date = $resultinfo["last_action_date_time"];
// Create the array of data to output:
$resultdata = array(
'tracking' => $tracking,
'order' => $order_no,
'status' => $status,
'date' => $date
);
if ($status == 'delivered') {
fputcsv($fp, $resultdata);
}
}
fclose($fp);
}

Is this the correct way to create and post a mutipart form data in CakePhp3?

I am trying to post a mutipart form data in CakePhp3. The form should contain a few information about the user (text fields) and an image.
I'm doing something like this:
$request = [
'fistname'=>$user->firstname,
'lastname'=>'$user->lastname',
'_session'=>'$session'
];
$form = new FormData();
foreach ($request as $key => $value) {
$form->add($key,$request);
}
$file = $form->addFile('upload',fopen(WWW_ROOT.'img/picture.png','r'));
$file->contentId('mypicture'); // <-- not sure what this is
$file->disposition('attachment');
$response = $http->post(
$url,
(string)$form,
['headers' => ['Content-Type' => $form->contentType()]]
);
Is this the correct way to create and post a mutipart form data in CakePhp3?
Thanks for your help.
EDIT
If I post to my own server it seems to be working (thanks #Mary), but I get firstname and lastname replicated (this might be the problem):
object(Cake\Http\ServerRequest) {
trustProxy => false
...
[protected] data => [
'fistname' => [
'fistname' => 'Test',
'lastname' => 'Test'
],
'lastname' => [
'fistname' => 'Test',
'lastname' => 'Test'
],
'upload' => [
'tmp_name' => '/private/var/folders/g5/jjd1vc557bs21hq805lcxjk80000gn/T/phpAVXNqK',
'error' => (int) 0,
'name' => 'SELL5BAE2B6348272_gallery_1.png',
'type' => 'image/png',
'size' => (int) 200231
]
]
...
If I post to the API server it doesn't work.
I did the same with CURL and it works:
$filename = WWW_ROOT.'ufiles/medium/'.$img['image_1'];
$cFile = curl_file_create($filename);
$request = [
'_operation'=>'uploadFile',
'id'=>$ticket_id,
'_session'=>$session,
'file' => $cFile
];
try{
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_URL,$this->crm['endpoint']);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$response=curl_exec($ch);
curl_close ($ch);
}catch(\Exception $e){
$response = null;
}
Counterquestion: Does it work?
As you can see here, $file->contentId() sets the Content ID or part in a multipart form data request body:
https://github.com/cakephp/cakephp/blob/master/src/Http/Client/FormDataPart.php#L114
I’m not sure about this, but I don’t think you have to set it as it doesn’t seem to be required for multipart/form-data:
https://www.w3.org/TR/2006/REC-xforms-20060314/slice11.html#serialize-form-data
Edit
I did some testing and: It. works. Here is what I tried:
use Cake\Http\Client;
use Cake\Http\Client\FormData;
public function test() {
$request = [
'fistname'=>'Test',
'lastname'=>'Test'
];
$form = new FormData();
$http = new Client();
foreach ($request as $key => $value) {
$form->add($key,$request);
}
$file = $form->addFile('upload',fopen(WWW_ROOT.'img/awards.png','r'));
$file->contentId('mypicture'); // <-- not sure what this is
$file->disposition('attachment');
$response = $http->post(
'http://www.testurl.dev/test',
(string)$form,
['headers' => ['Content-Type' => $form->contentType()]]
);
var_dump($response);
exit;
}
Output of var_dump($response):
object(Cake\Http\Client\Response)#150 (12) {
["code":protected]=>int(200)
…
["headers":protected]=>array(12) {
["Date"]=>array(1) {
[0]=>string(29) "Fri, 28 Sep 2018 12:44:31 GMT"
}
…
}
}
Server access log output:
[28/Sep/2018:14:44:31 +0200] "POST /test HTTP/1.1" 200 6852 "-" "CakePHP"

Invalid Signature Coinbase

I'm trying to use the API for Coinbase but I get invalid signature.
So probably I'm actually sign it wrong or I'm missing something.
what should I use on request? should i use POST or GET on method?
$urlapi = "https://api.coinbase.com/v2/time";
$Key = "--------------";
$Secret = "------------";
$fecha = new DateTime();
$timestamp = $fecha->getTimestamp();
$request="";
$body="";
$method="GET";
$Datas = $timestamp . $method . $request . $body;
$hmacSig = hash_hmac('sha256',$Datas,$Secret);
$curl = curl_init($urlapi);
curl_setopt($curl,CURLOPT_HTTPHEADER,array('Content-Type: application/json','CB-ACCESS-KEY: '.$Key,'CB-VERSION: 2015-07-07','CB-ACCESS-TIMESTAMP: '. $timestamp,'CB-ACCESS-SIGN: '.$hmacSig));
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$resp = curl_exec($curl);
if(!curl_exec($curl)){
die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
}
curl_close($curl);
print_r($resp);
Get Current Time is a GET request (ref). The HTTP verb (GET/POST etc.) can be found in the docs for each type of request here:
In your example, the problem is that the $request variable in your message is blank. It should be $request="/v2/time";
hash_hmac returns hex encoded string by default so the hashing part is correct.
define('API_KEY', 'xxxx');
define('API_SECRET', 'xxxxxxxxx');
define('API_BASE', 'https://api.coinbase.com');
define('API_VERSION', '2015-08-31');
$headers = array(
'Content-Type: application/json',
'CB-VERSION: ' . API_VERSION
);
$url = API_BASE.'/v2/time';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
$output = json_decode($response, true);
print_r($output);
will return
Array ( [data] => Array ( [iso] => 2015-12-01T10:35:58Z [epoch] => 1448966158 ) )
You must use GET method, because is just to get some information, authentication is no needed.
This is an easier way:
$time = file_get_contents('https://api.coinbase.com/v2/time');
$time = json_decode($time);
$time = $time->data->epoch;

Global variable change to null after calling an action in controller

I want to call delete action, but my global variable sets to null.
Controller:
App::uses('AppController', 'Controller');
class WhitelistController extends AppController
{
public $helpers = array('Html', 'Form');
private $deletes;
public function index()
{
if ($this->request->is('post'))
{
$whitelist = $_POST['data']['whitelist']['stylecodes'];
if($whitelist == "")
return $this->Session->setFlash('You did not enter stylecodes. If you send this, it will delete all the shoes from the website.');
$whitelist = preg_replace('/\s+/', '', $whitelist);
$whitelist = explode(",", $whitelist);
$url = 'http://fonda.vps.***********/product_import_json_all_published_products';
$ch = curl_init($url);
curl_setopt( $ch, CURLOPT_POST, 1);
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt( $ch, CURLOPT_HEADER, 0);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1);
$all = curl_exec($ch);
$all = json_decode($all, true);
print_r($all);
$this->deletes = array_diff($all, $whitelist);
if($this->deletes == $all)
return $this->Session->setFlash('It seems you entered wrong data, what could delete all of the shoes from the website.');
$this->deletes = array_values($this->deletes);
pr($this->deletes);
$this->set('delete', $this->deletes);
$this->render('delete');
}
}
public function delete()
{
if($this->request->is('post'))
{
}else{
$url = 'http://fonda.vps.*******/product_import_json_remove';
$myvars = 'products=' . json_encode($this->deletes);
print_r();
pr($myvars);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $myvars);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$response = json_decode($response, true);
pr($response);
$removed = count($response['removed']);
$skipped = count($response['skipped']);
$string = $removed . " shoe(s) removed and " . $skipped . " shoe(s) skipped.";
$this->Session->setFlash($string);
if (count($response['error']) != 0) {
$string = "";
echo " ";
foreach ($response['error'] as $key => $value) {
$string .= $key . ": " . $value;
$string .= "\n";
}
$this->Session->setFlash('Error found in following shoe(s): ' . $string);
}
return $this->redirect(array( 'action' => 'index'));
}
}
}
$this->deletes gets null after calling the delete() from the view.
I don't see anything that changes the deletes value.
What is the problem?
I think I figured it out. I removed the global variable, and i put the local variable to a session in the first action:
$this->Session->write('deletes', $delete);
And i read it in the second action like this:
$delete = $this->Session->read('deletes');
so i could work with the $delete in the second action.

Send file using multipart/form-data request in php

I have image resource stored in variable which I need to send to server using its http API and PHP. I have to send request with content type multipart/form-data. So, I need to make similiar request as when form with file input and enctype=multipart/form-data attribute is sent.
I tried this:
<?php
$url = 'here_is_url_for_web_API';
$input = fopen('delfin.jpg','r');
$header = array('Content-Type: multipart/form-data');
$resource = curl_init();
curl_setopt($resource, CURLOPT_URL, $url);
curl_setopt($resource, CURLOPT_USERPWD, "user:password");
curl_setopt($resource, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE);
curl_setopt($resource, CURLOPT_HTTPHEADER, $header);
curl_setopt($resource, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($resource, CURLOPT_BINARYTRANSFER, true );
curl_setopt($resource, CURLOPT_INFILESIZE, 61631);
curl_setopt($resource, CURLOPT_INFILE, $input);
$result = curl_exec($resource);
curl_close($resource);
var_dump($result);
?>
I don't know how exactly response should look like but this returns:
http status 405
and error report is: The specified HTTP method is not allowed for the requested resource ().
use multipart/form-data and boundaries in POST content with curl.
$filenames = array("/tmp/1.jpg", "/tmp/2.png");
$files = array();
foreach ($filenames as $f){
$files[$f] = file_get_contents($f);
}
// more fields for POST request
$fields = array("f1"=>"value1", "another_field2"=>"anothervalue");
$url = "http://example.com/upload";
$curl = curl_init();
$url_data = http_build_query($data);
$boundary = uniqid();
$delimiter = '-------------' . $boundary;
$post_data = build_data_files($boundary, $fields, $files);
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
//CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $post_data,
CURLOPT_HTTPHEADER => array(
//"Authorization: Bearer $TOKEN",
"Content-Type: multipart/form-data; boundary=" . $delimiter,
"Content-Length: " . strlen($post_data)
)
));
//
$response = curl_exec($curl);
$info = curl_getinfo($curl);
//echo "code: ${info['http_code']}";
//print_r($info['request_header']);
var_dump($response);
$err = curl_error($curl);
echo "error";
var_dump($err);
curl_close($curl);
function build_data_files($boundary, $fields, $files){
$data = '';
$eol = "\r\n";
$delimiter = '-------------' . $boundary;
foreach ($fields as $name => $content) {
$data .= "--" . $delimiter . $eol
. 'Content-Disposition: form-data; name="' . $name . "\"".$eol.$eol
. $content . $eol;
}
foreach ($files as $name => $content) {
$data .= "--" . $delimiter . $eol
. 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . $eol
//. 'Content-Type: image/png'.$eol
. 'Content-Transfer-Encoding: binary'.$eol;
$data .= $eol;
$data .= $content . $eol;
}
$data .= "--" . $delimiter . "--".$eol;
return $data;
}
See the full example here: https://gist.github.com/maxivak/18fcac476a2f4ea02e5f80b303811d5f
If you work with CURL, you have to just:
1, set header 'Content-Type' as 'multipart/form-data;'
2, set option 'RETURNTRANSFER' of curl to true (use option method of curl)
3, set option 'POST' of curl to true (use option method of curl)
4, get source of your file (what you get from fopen in PHP):
$tempFile = tempnam(sys_get_temp_dir(), 'File_');
file_put_contents($tempFile, $source);
$post = array(
"uploadedFile" => "#" . $tempFile, //"#".$tempFile.";type=image/jpeg",
);
5, use post method of CURL with parameter in $post variable

Resources