この記事は2018年03月04日にqiitaに投稿した内容です。
環境
Unity2017.3.0p4 Windows10
概要
UnityからBitpointの価格情報のwebsocketのapiにアクセスしようとしたが、うまくいきませんでした。 仕方ないのでNodeJsからSockJs-Clientを使用して情報を取得、HttpServerを立て、HttpリクエストしてきたUnityに情報を返しています。
GoogleComputeEngineの設定、WinScpの設定
以下を参照して設定する サーバのIPアドレス(外部IP)をメモしておく GoogleComputeEngineのVMインスタンスにWinScpでログイン
プログラムのアップロード
WinScpを用いて後述の「bitpoint.js」と「serverBitpoint.sh」をアップロードし、パーミッションで実行権限を付与する ・WinScp上でファイルを選択し、プロパティから行う
NodeJsのインストール
SSHでサーバにログインし、「Putty」のコマンドラインを開く 「sudo yum install -y nodejs」と入力
opensslの更新
「sudo yum update openssl」と入力
モジュールのダウンロード
js内で参照しているモジュールをダウンロードする
・「npm init」と入力 色々聞かれるがそのままリターン package.jsonができる ・「npm install -save XXX」と入力 -saveでpackage.jsonにモジュール情報が保存される XXXはモジュール名 Bitpoint.js内でrequireしているもの 「node Bitpoint.js」と入力してエラーが出るものが足りないもの request sockjs-client date-utils ※他にもエラーと言われるものがあるかもしれない
プログラムの実行
「nohup ./serverBitpoint.sh &」と入力
プログラム
アクセストークンを取得しているがこれはダミー。 USERNAMEとPASSWORDもダミー なぜか実行しないとwebsocketに通信できなかった(気のせいかもしれない) bitpoint.js
const Crypto = require("crypto");
const Request = require('request');
const SockJS = require('sockjs-client');
const Http = require('http');
const Url = require('url');
const Qs = require('querystring');
require('date-utils');
const USERNAME = "hogehoge@hoge.com";
const PASSWORD = "fugafuga";
var _server;
Main();
function Main()
{
GetAccessToken();
CreateHttpServer();
}
function GetAccessToken()
{
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var sha256 = Crypto.createHash('sha256');
sha256.update(PASSWORD);
var hash = sha256.digest('hex')
Request.get(`https://public.bitpoint.co.jp/bpj-api/login?username=${USERNAME}&password=${hash}`, (error, response, body) =>
{
var accessToken = JSON.parse(body)['access_token'];
console.log( 'access_token', accessToken );
});
}
function CreateHttpServer()
{
_server = Http.createServer();
_server.on('request', function( req, res )
{
console.log("Method = ", req.method);
console.log("STATUS: ", res.statusCode);
console.log("Content-Type: ", res.getHeader("Content-Type") );
var getParams = Url.parse( req.url, true );
console.log( "Get:", getParams.query );
if( req.method == 'POST' )
{
var body='';
req.on( 'data', function( data )
{
body += data;
});
req.on( 'end', function()
{
var postParams = Qs.parse( body );
console.log( "Post:", postParams );
HttpResponse( req, res, getParams, postParams );
});
}
else
HttpResponse( req, res, getParams, null );
});
_server.listen(8080)
console.log('Start Server');
}
function HttpResponse( req, res, getParams, postParams )
{
var Responses =
{
"Default": function ()
{
res.writeHead(200, {'Content-Type': 'application/json'});
var now = new Date().toFormat("YYYYMMDDHH24MISS");
res.end( `{ "time":"${now}" }` );
},
"leverageTwoWay": function ()
{
var accessToken = ( getParams.query[ "access_token" ] ) ? getParams.query[ "access_token" ] : "";
RequestLeverageTwoWay( accessToken, postParams, function( response )
{
res.writeHead(200, {'Content-Type': 'application/json'});
res.end( response );
});
}
}
var uri = Url.parse(req.url).pathname;
if (uri === "/")
{
Responses["Default"]();
return;
}
else if (uri === "/leverageTwoWay")
{
Responses["leverageTwoWay"]();
return;
}
}
function RequestLeverageTwoWay( accessToken, postParams, onResponse )
{
var response = '{ "error":"" }';
if( accessToken == "" )
{
response = '{ "error":"accessToken" }';
console.log( response );
onResponse( response );
return;
}
if( postParams == null )
{
response = '{ "error":"postParams" }';
console.log( response );
onResponse( response );
return;
}
var options = postParams;//{ 'server': '{"currencyCd1":"BTC","currencyCd2":"JPY"}' };
const sock = new SockJS(`https://public.bitpoint.co.jp/bpj-api/leverageTwoWay?access_token=${accessToken}`, null, options );
sock.onopen = function()
{
console.log( "Open:", sock.url );
};
sock.onmessage = function(e)
{
console.log( "Message:", e.data );
var now = new Date().toFormat("YYYYMMDDHH24MISS");
response = `{ "updatetime":"${now}", "data":${e.data} }`;
sock.close();
};
sock.onclose = function()
{
console.log( "Close:", sock.url );
onResponse( response );
};
}
serverBitpoint.sh
#!/bin/bash
node bitpoint.js
クライアントプログラム
ApiLogin.Requestを呼び出し、AccessTokenを取得 ApiLeverageTwoWay.Requestを呼び出し、建てたサーバから価格情報を取得 返ってきたjsonは何らかのパーサーでクラスとかにする
・アクセストークンの取得 「XXXX,YYYY」はBitpointのLogin時のメールアドレスとパスワード Assets/ApiLogin.cs
public class ApiLogin
{
public static Coroutine Request( ExchangeBitpoint exchange, UnityAction<string> onResponse )
{
var sha256 = SHA256.Create();
var hash = sha256.ComputeHash( Encoding.ASCII.GetBytes( YYYY ) );
var password = BitConverter.ToString( hash ).Replace("-", "").ToLower();
var param = new Dictionary<string, string>();
param[ "username" ] = XXXX;
param[ "password" ] = password;
var query = exchange.GenerateFormParameter( param );
var api = "/login";
return exchange.Request( RequestType.Get, api + '?' + query, null, onResponse );
}
public class Response
{
public string access_token { get; set; }
}
}
Assets/ApiLeverageTwoWay.cs
public class ApiLeverageTwoWay
{
public static Coroutine Request( ExchangeBitpoint exchange, string accessToken, UnityAction<string> onResponse )
{
var query = "{ \"currencyCd1\":\"BTC\", \"currencyCd2\":\"JPY\" }";
var api = "/leverageTwoWay";
return exchange.Request( RequestType.RelayPost, api + "?access_token=" + accessToken, query, onResponse );
}
public class Response
{
public class Datum
{
public string currencyCd1 { get; set; }
public string currencyCd2 { get; set; }
public decimal seq { get; set; }
public decimal buySellCls { get; set; }
public string indicator { get; set; }
public decimal price { get; set; }
public decimal openPrice { get; set; }
public decimal highPrice { get; set; }
public decimal lowPrice { get; set; }
public decimal preClosePrice { get; set; }
public string priceDate { get; set; }
public string openPriceDate { get; set; }
public string highPriceDate { get; set; }
public string lowPriceDate { get; set; }
public string preClosePriceDate { get; set; }
public decimal change { get; set; }
public decimal changeRate { get; set; }
}
public string updatetime { get; set; }
public string error { get; set; }
public List<Datum> data { get; set; }
}
}
Assets/ExchangeBitpoint.cs ・「RequestType.RelayPost」でリクエストが呼ばれたときは自分が建てたサーバが呼ばれるようにしている XXXXにサーバのIpアドレスを入れる
using System;
using System.Collections;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Text;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
public enum RequestType
{
Get,
Post,
Delete,
RelayPost, //Bitpoint
}
public class ExchangeBitpoint : MonoBehaviour
{
private RemoteCertificateValidationCallback _remoteCertificateValidationCallback = new RemoteCertificateValidationCallback( ( sender, certificate, chain, sslPolicyErrors ) => { return true; } );
public string GenerateFormParameter( Dictionary<string, string > dictForm )
{
string formParam = "";
var count = dictForm.Count;
var index = 0;
foreach( var pair in dictForm )
{
formParam += pair.Key + "=" + pair.Value;
index++;
if( index < count )
formParam += "&";
}
return formParam;
}
public Coroutine Request( RequestType type, string path, object query, UnityAction<string> onResponse, int timeout = 0 )
{
return StartCoroutine( OpRequest( type, path, query as string, onResponse, timeout ) );
}
protected IEnumerator OpRequest( RequestType type, string path, string query, UnityAction<string> onResponse, int timeout )
{
var url = "";
if( type != RequestType.RelayPost )
url = "https://public.bitpoint.co.jp/bpj-api" + path;
else
url = "http://XXXX:8080" + path;
var prevCertCallback = ServicePointManager.ServerCertificateValidationCallback;
ServicePointManager.ServerCertificateValidationCallback = _remoteCertificateValidationCallback;
var httpRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create( url );
switch( type )
{
case RequestType.Get:
httpRequest.Method = "GET";
break;
default:
httpRequest.Method = "POST";
httpRequest.ContentType = "application/json";
byte[] bodyRaw = ( query != null ) ? Encoding.UTF8.GetBytes( query ) : null;
httpRequest.ContentLength = bodyRaw.Length;
var isRequest = false;
httpRequest.BeginGetRequestStream( ( ar ) =>
{
System.IO.Stream reqStream = httpRequest.EndGetRequestStream( ar );
//送信するデータを書き込む
reqStream.Write( bodyRaw, 0, bodyRaw.Length );
reqStream.Close();
isRequest = true;
}, null );
while( isRequest == false )
yield return null;
break;
}
string text = null;
bool isResponse = false;
httpRequest.BeginGetResponse( ( ar ) =>
{
var response = (System.Net.HttpWebResponse)httpRequest.EndGetResponse( ar );
var statusCode = (int)response.StatusCode;
System.IO.Stream resStream = response.GetResponseStream();
//受信して表示
System.IO.StreamReader sr = new System.IO.StreamReader( resStream, System.Text.Encoding.UTF8 );
text = sr.ReadToEnd();
sr.Close();
// response.Close();
isResponse = true;
}, null );
while( isResponse == false )
yield return null;
ServicePointManager.ServerCertificateValidationCallback = prevCertCallback;
if( onResponse != null )
onResponse( text );
yield break;
}
}