Skip to content

Commit ba0ea42

Browse files
author
ghostjat
committed
base
Signed-off-by:ghostjat <[email protected]>
1 parent 85b784b commit ba0ea42

File tree

3 files changed

+262
-0
lines changed

3 files changed

+262
-0
lines changed

cred.ini

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; this is cred file
2+
[cred]
3+
uid = 'Your User ID'
4+
pwd ='Your Password'
5+
factor2 = 'Your DOB or PAN'
6+
vc = 'Your VC'
7+
appkey = 'Your Api Key'
8+
imei = 'Your IMEI'
9+
apkversion = '1.0.0'
10+
source = 'API'

index.php

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
require_once 'vendor/autoload.php';
4+
5+
date_default_timezone_set('Asia/Kolkata');
6+
7+
use Core\Api\Shoonya;
8+
9+
$api = new Shoonya();
10+
if($api->login()) {
11+
echo 'Successfully Login....' .PHP_EOL;
12+
$holdings = $api->getPositions();
13+
print_r($holdings);
14+
}
15+
16+
17+
18+
if($api->logout()){
19+
echo 'Successfully Logout....' .PHP_EOL;
20+
}
21+
22+

src/Api/Shoonya.php

+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
<?php
2+
3+
namespace Core\Api;
4+
5+
use GuzzleHttp\Client;
6+
7+
class Shoonya {
8+
9+
protected $guzzle, $jKey, $userName, $accountId, $pwd, $uid;
10+
protected $cred,$orderNo = [];
11+
protected const Delivery = 'C', Intraday = 'I', Normal = 'M', CF = 'M';
12+
13+
protected $urls = [
14+
'host' => 'https://shoonyatrade.finvasia.com/',
15+
'websocket_endpoint' => 'wss://shoonyatrade.finvasia.com/NorenWSTP',
16+
'endpoint' => 'https://shoonyatrade.finvasia.com/NorenWClientTP',
17+
"eodhost" => 'https://shoonya.finvasia.com/chartApi/getdata',
18+
];
19+
protected $routes = [
20+
'login' => '/QuickAuth',
21+
'logout' => '/Logout',
22+
'forgot_password' => '/ForgotPassword',
23+
'change_password' => '/Changepwd',
24+
'watchlist_names' => '/MWList',
25+
'watchlist' => '/MarketWatch',
26+
'watchlist_add' => '/AddMultiScripsToMW',
27+
'watchlist_delete' => '/DeleteMultiMWScrips',
28+
'placeorder' => '/PlaceOrder',
29+
'modifyorder' => '/ModifyOrder',
30+
'cancelorder' => '/CancelOrder',
31+
'exitorder' => '/ExitSNOOrder',
32+
'product_conversion' => '/ProductConversion',
33+
'orderbook' => '/OrderBook',
34+
'tradebook' => '/TradeBook',
35+
'singleorderhistory' => '/SingleOrdHist',
36+
'searchscrip' => '/SearchScrip',
37+
'TPSeries' => '/TPSeries',
38+
'optionchain' => '/GetOptionChain',
39+
'holdings' => '/Holdings',
40+
'limits' => '/Limits',
41+
'positions' => '/PositionBook',
42+
'scripinfo' => '/GetSecurityInfo',
43+
'getquotes' => '/GetQuotes',
44+
];
45+
46+
public function __construct() {
47+
$this->cred = parse_ini_file('cred.ini');
48+
$this->guzzle = new Client();
49+
}
50+
51+
/**
52+
*
53+
* @return bool
54+
* @throws ErrorException
55+
*/
56+
public function login():bool {
57+
$this->cred['pwd'] = hash('sha256', utf8_encode($this->cred['pwd']));
58+
$this->cred['appkey'] = hash('sha256', utf8_encode($this->cred['uid'] . '|' . $this->cred['appkey']));
59+
$request = $this->post($this->urls['endpoint'], $this->routes['login'], $this->jData($this->cred));
60+
$decode = $this->decode($request->getBody());
61+
if ($decode->stat != 'Ok') {
62+
throw new ErrorException($decode->emsg, $request->getStatusCode(), 'LoginError');
63+
}
64+
$this->jKey = $decode->susertoken;
65+
$this->userName = $decode->actid;
66+
$this->accountId = $decode->actid;
67+
$this->uid = $this->cred['uid'];
68+
return true;
69+
}
70+
71+
/**
72+
*
73+
* @return bool
74+
* @throws ErrorException
75+
*/
76+
public function logout() :bool {
77+
$body = $this->jData(['ordersource' => 'API', 'uid' => $this->uid]) . $this->jKey();
78+
$request = $this->post($this->urls['endpoint'], $this->routes['logout'], $body);
79+
$decode = $this->decode($request->getBody());
80+
if ($decode->stat != 'Ok') {
81+
throw new ErrorException($decode->emsg, $request->getStatusCode(), 'LogoutError');
82+
}
83+
$this->jKey = null;
84+
$this->userName = null;
85+
$this->accountId = null;
86+
$this->uid = null;
87+
return true;
88+
}
89+
90+
/**
91+
*
92+
* @param string $exchange
93+
* @param string $searchtext
94+
* @return array
95+
* @throws ErrorException
96+
*/
97+
public function searchScrip(string $exchange, string $searchtext):array {
98+
if ($searchtext == null) {
99+
throw new ErrorException('search text cannot be null');
100+
}
101+
102+
$values = [
103+
'uid' => $this->uid,
104+
'exch' => $exchange,
105+
'stext' => ($searchtext) // urllib . parse . quote_plus
106+
];
107+
108+
$body = $this->jData($values) . $this->jKey();
109+
110+
$request = $this->post($this->urls['endpoint'], $this->routes['searchscrip'], $body);
111+
$decode = $this->decode($request->getBody());
112+
if ($decode->stat != 'Ok') {
113+
throw new ErrorException($decode->emsg, $request->getStatusCode(), 'ScripSearch-Error');
114+
}
115+
return $decode->values;
116+
}
117+
118+
/**
119+
*
120+
* @param string $productType
121+
* @return array
122+
* @throws ErrorException
123+
*/
124+
public function getHoldings($productType = self::Delivery):array {
125+
126+
$values = [
127+
'uid ' => $this->userName,
128+
'actid' => $this->accountId,
129+
'prd' => $productType
130+
];
131+
132+
$body = $this->jData($values) . $this->jKey();
133+
$request = $this->post($this->urls['endpoint'], $this->routes['holdings'], $body);
134+
$decode = $this->decode($request->getBody());
135+
if ($decode->stat != 'Ok') {
136+
throw new ErrorException($decode->emsg, $request->getStatusCode(), 'GetHolding-Error');
137+
}
138+
return $decode;
139+
}
140+
141+
/**
142+
*
143+
* @return array
144+
* @throws ErrorException
145+
*/
146+
public function getPositions():array{
147+
$values = [
148+
'uid ' => $this->userName,
149+
'actid' => $this->accountId
150+
];
151+
$body = $this->jData($values).$this->jKey();
152+
$request = $this->post($this->urls['endpoint'], $this->routes['positions'], $body);
153+
$decode = $this->decode($request->getBody());
154+
if ($decode->stat != 'Ok') {
155+
throw new ErrorException($decode->emsg, $request->getStatusCode(), 'GetPosition-Error');
156+
}
157+
return $decode;
158+
}
159+
160+
public function placeOrder($buy_or_sell, $productType, $exchange, $tradingSymbol, $quantity, $discloseQty,
161+
$priceType, $price = 0.0, $triggerPrice = null, $retention = 'DAY', $amo = 'NO', $remarks = null,
162+
$booklossPrice = 0.0, $bookprofitPrice = 0.0, $trailPrice = 0.0) {
163+
164+
#prepare the data
165+
$values = ['ordersource' => 'API',
166+
'uid' => $this->uid,
167+
'actid' => $this->accountId,
168+
'trantype' => $buy_or_sell,
169+
'prd' => $productType,
170+
'exch' => $exchange,
171+
'tsym' => ($tradingSymbol), //urllib . parse . quote_plus
172+
'qty' => string($quantity),
173+
'dscqty' => string($discloseQty),
174+
'prctyp' => $priceType,
175+
'prc' => string($price),
176+
'trgprc' => string($triggerPrice),
177+
'ret' => $retention,
178+
'remarks' => $remarks,
179+
'amo' => $amo
180+
];
181+
182+
#if cover order or high leverage order
183+
if ($productType == 'H') {
184+
$values["blprc"] = string($booklossPrice);
185+
#trailing price
186+
if ($trailPrice != 0.0) {
187+
$values["trailprc"] = string($trailPrice);
188+
}
189+
}
190+
191+
#bracket order
192+
if ($productType == 'B') {
193+
$values["blprc"] = string($booklossPrice);
194+
$values["bpprc"] = string($bookprofitPrice);
195+
#trailing price
196+
if ($trailPrice != 0.0) {
197+
$values["trailprc"] = string($trailPrice);
198+
}
199+
}
200+
201+
$body = $this->jData($values) . $this->jKey();
202+
$request = $this->post($this->urls['endpoint'], $this->routes['placeorder'], $body);
203+
$decode = $this->decode($request->getBody());
204+
if ($decode->stat != 'Ok') {
205+
throw new ErrorException($decode->emsg, $request->getStatusCode(), 'OrderPlacing-Error');
206+
}
207+
$this->orderNo[] = $decode->norenordno;
208+
return true;
209+
}
210+
211+
protected function decode($jsonData) {
212+
return json_decode($jsonData);
213+
}
214+
215+
protected function post($urls, $routes, $body, $contentType = 'application/json') {
216+
return $this->guzzle->post($urls . $routes, [
217+
'header' => ['Content-Type' => $contentType],
218+
'body' => $body
219+
]);
220+
}
221+
222+
protected function jData($data) {
223+
return 'jData=' . json_encode($data);
224+
}
225+
226+
protected function jKey() {
227+
return '&jKey=' . $this->jKey;
228+
}
229+
230+
}

0 commit comments

Comments
 (0)