KangApi.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. <?php
  2. namespace app\common\logic;
  3. use app\api\controller\Offline as OfflineApi;
  4. use app\common\model\OfflineWithdrawRecordModel;
  5. use app\common\model\ParametersModel;
  6. use think\Cache;
  7. use think\Env;
  8. use think\Log;
  9. /**
  10. * KKK的出款钱包API
  11. *
  12. * API文档:http://8.222.240.131:8079/doc.html
  13. */
  14. class KangApi
  15. {
  16. protected $urls = 'http://8.222.240.131:8079/';
  17. protected $api_key = null;
  18. protected $api_pwd = null;
  19. protected $bnb_fee = 0.005;
  20. /*
  21. * 获取BNB余额
  22. */
  23. public function getBalance(string $address)
  24. {
  25. $api_url = $this->urls . 'coinBalance/getBalance?';
  26. $api_url .= 'address=' . $address;
  27. $api_url .= '&coinType=bsc';
  28. $get_data = $this->curlGetData($api_url);
  29. if(empty($get_data)){
  30. return _error('API返回结果为空');
  31. }
  32. $get_data = json_decode($get_data, true);
  33. //返回数据结构
  34. //{
  35. // "code": 200,
  36. // "msg": "操作成功",
  37. // "data": 0.166243248
  38. //}
  39. if($get_data['code'] == 200){
  40. return _success($get_data['data']);
  41. }
  42. return _error($get_data['msg']);
  43. }
  44. /*
  45. * 获取代币合约余额,默认为USDT
  46. *
  47. * $contract 合约地址
  48. * $decimal 合约地址精度
  49. */
  50. public function getTokenBalance(string $address, string $contract = '0x55d398326f99059fF775485246999027B3197955', int $decimal = 18)
  51. {
  52. $api_url = $this->urls . 'coinBalance/getTokenBalance?';
  53. $api_url .= 'address=' . $address;
  54. $api_url .= '&coinType=bsc';
  55. $api_url .= '&contract=' . $contract;
  56. $api_url .= '&decimal=' . $decimal;
  57. $get_data = $this->curlGetData($api_url);
  58. if(empty($get_data)){
  59. return _error('API返回结果为空');
  60. }
  61. $get_data = json_decode($get_data, true);
  62. //返回数据结构
  63. //{
  64. // "code": 200,
  65. // "msg": "操作成功",
  66. // "data": 0.166243248
  67. //}
  68. if($get_data['code'] == 200){
  69. return _success($get_data['data']);
  70. }
  71. return _error($get_data['msg']);
  72. }
  73. public function createWithdraw(string $order_id)
  74. {
  75. $order_info = (new OfflineWithdrawRecordModel())
  76. ->fetchSql(false)
  77. ->field('w.id,u.address,w.status,w.real_amount')
  78. ->alias('w')
  79. ->join('user u', 'u.id = w.user_id')
  80. ->where('w.id', $order_id)
  81. ->find();
  82. if(empty($order_info)){
  83. return _error('提现订单不存在');
  84. }
  85. if($order_info['status'] != 0){
  86. return _error('该订单当前状态不可提现');
  87. }
  88. if(!Cache::has('usdt_balance')){
  89. //手续费
  90. $fee = $this->getBalance(Env::get('rental.out_address'));
  91. if ($fee['code'] != 1){
  92. return _error('获取手续费失败');
  93. }
  94. $reqFee = $fee['data'];
  95. if($reqFee > 0){
  96. $reqFee = round($fee['data'], 6);
  97. }
  98. if ($reqFee < $this->bnb_fee){
  99. return _error("BNB手续费不足,不能低于:" . $this->bnb_fee);
  100. }
  101. //Usdt余额
  102. $balan = $this->getTokenBalance((Env::get('rental.out_address')));
  103. if ($balan['code'] != 1){
  104. return _error('获取USDT余额失败:'. $balan['msg']);
  105. }
  106. $reqBalance = round($balan['data'], 6);
  107. Cache::set('usdt_balance', $reqBalance, 1800);//钱包余额
  108. Cache::set('use_amount', 0, 1800);//使用额度
  109. }
  110. $usdt_balance = Cache::get('usdt_balance');
  111. $use_amount = Cache::get('use_amount');
  112. $remaining_amount = $usdt_balance - $use_amount;
  113. if ($remaining_amount < $order_info['real_amount']){
  114. return _error("USDT余额不足,半小时内可提现额度:" . $usdt_balance . ',剩余额度:' . $remaining_amount);
  115. }
  116. $this->api_key = Env::get('rental.kang_api_key');
  117. $this->api_pwd = (new ParametersModel())->getValue('kangApiPwd');
  118. $req = $this->withdraw($order_info['address'],$order_info['real_amount'],$order_info['id'],$this->api_key, $this->api_pwd);
  119. if($req['code'] == 0){
  120. return _error($req['msg']);
  121. }
  122. return _success();
  123. }
  124. /**
  125. * 新增提现
  126. */
  127. protected function withdraw(string $address, float $mum, string $order_sn, string $api_key, string $api_pwd)
  128. {
  129. $data = [
  130. 'apiKey' => $api_key,
  131. 'toAddress' => $address,
  132. 'coinName' => 'usdt',
  133. 'coinType' => 'bsc',
  134. 'mum' => $mum,//提币数量
  135. 'companyWithdrawId' => $order_sn//本平台的唯一订单号
  136. ];
  137. $data['sign'] = md5($this->getSignKey($data, $api_pwd));
  138. $api_url = $this->urls . 'coinWithdraw/withdraw';
  139. $get_data = $this->curlPostData($api_url, $data);
  140. if(empty($get_data)){
  141. return _error('API返回结果为空');
  142. }
  143. $get_data = json_decode($get_data, true);
  144. //返回数据结构
  145. //{
  146. // "code": 200,
  147. // "msg": "操作成功",
  148. // "data": 0.166243248
  149. //}
  150. $data['url'] = $api_url;
  151. $data['msg'] = $get_data['msg'];
  152. paymentLog($data);
  153. if($get_data['code'] == 200){
  154. return _success($get_data['data']);
  155. }
  156. return _error($get_data['msg']);
  157. }
  158. /**
  159. * 提现自动打款回调
  160. *
  161. * 接口回调信息格式:
  162. * companyWithdrawId=126&sign=8e3c6aee53e3ea4ff974c1d80f4e8beb&status=1&txId=0x39ce05a0698ff2b7459ca707703fd48937dd958422d98ebade6b4f5188b70995
  163. */
  164. public function withdrawCallback()
  165. {
  166. // $body1 = file_get_contents("php://input");
  167. // Log::write('提现自动打款回调1:' . $body1, 'info');
  168. //
  169. // $body = $this->request->post();
  170. $body = file_get_contents("php://input");
  171. //$body = 'companyWithdrawId=126&sign=8e3c6aee53e3ea4ff974c1d80f4e8beb&status=1&txId=0x39ce05a0698ff2b7459ca707703fd48937dd958422d98ebade6b4f5188b70995';
  172. Log::write('提现自动打款回调:' . $body, 'info');
  173. if(empty($body)){
  174. return _error('回调内容为空');
  175. }
  176. $parems = explode('&', $body);
  177. $req_arr = [];
  178. foreach ($parems as $item){
  179. $temp = explode('=', $item);
  180. $req_arr[$temp[0]] = $temp[1];
  181. }
  182. Log::write('提现自动打款回调参数:','info');
  183. Log::info(json_encode($req_arr));
  184. return _success($req_arr);
  185. }
  186. /**
  187. * 设置回调url
  188. *
  189. * 设置 api_key对应的回调地址
  190. *
  191. * url_type 通知地址类型 1充值 2提现
  192. */
  193. public function configNotice(string $api_key, string $api_pwd, string $url, int $url_type = 1)
  194. {
  195. $data = [
  196. 'apiKey' => $api_key,
  197. 'noticeUrl' => $url,
  198. 'urlType' => $url_type,
  199. ];
  200. $data['sign'] = md5($this->getSignKey($data, $api_pwd));
  201. $api_url = $this->urls . 'walletCollectTask/configNotice';
  202. dump($data);
  203. $get_data = $this->curlPostData($api_url, $data);
  204. if(empty($get_data)){
  205. return _error('API返回结果为空');
  206. }
  207. $get_data = json_decode($get_data, true);
  208. //返回数据结构
  209. //{
  210. // "code": 200,
  211. // "msg": "操作成功",
  212. // "data": null
  213. //}
  214. if($get_data['code'] == 200){
  215. return _success($get_data['data']);
  216. }
  217. return _error($get_data['msg']);
  218. }
  219. /**
  220. * 获取签名-带连接符号
  221. * @return string
  222. */
  223. protected function getSignKey(array $arr, string $secretKey)//: string
  224. {
  225. ksort($arr);
  226. $arr['apiSecret'] = $secretKey;
  227. $string = '';
  228. foreach ($arr as $key => $value)
  229. $string .= '&'.$key .'='.$value;
  230. return ltrim($string, '&');
  231. }
  232. /*
  233. * 封装Get请求
  234. */
  235. private function curlGetData($url){
  236. Log::info('查询余额');
  237. Log::info($url);
  238. # 初始化一个curl会话
  239. $ch = curl_init();
  240. # 判断是否是https
  241. if (stripos($url, "https://") !== false) {
  242. # 禁用后cURL将终止从服务端进行验证
  243. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  244. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  245. # 使用的SSL版本(2 或 3)
  246. curl_setopt($ch, CURLOPT_SSLVERSION, 1);
  247. }
  248. # 设置请求地址
  249. curl_setopt($ch, CURLOPT_URL, $url);
  250. # 在启用CURLOPT_RETURNTRANSFER的时候,返回原生的(Raw)输出
  251. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  252. # 执行这个请求
  253. $output = curl_exec($ch);
  254. # 关闭这个请求
  255. curl_close($ch);
  256. return $output;
  257. }
  258. /*
  259. * 封装Post请求
  260. */
  261. private function curlPostData($url , $data=array())
  262. {
  263. $headers = array("Content-type:application/x-www-form-urlencoded;charset=UTF-8");
  264. $ch = curl_init();
  265. curl_setopt($ch, CURLOPT_URL, $url);
  266. curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
  267. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  268. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  269. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  270. // POST数据
  271. curl_setopt($ch, CURLOPT_POST, 1);
  272. // 把post的变量加上
  273. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
  274. $output = curl_exec($ch);
  275. curl_close($ch);
  276. return $output;
  277. }
  278. }