// +---------------------------------------------------------------------- namespace App\Services; use App\Models\BalanceLogModel; use Cregis\Dispatch\CregisDispatch; /** * Cregis U盾钱包服务管理-服务类 * @author laravel开发员 * @since 2020/11/11 * @package App\Services */ class CregisPayService extends BaseService { // 静态对象 protected static $instance = null; protected $dispatch = null; protected static $config = []; public function __construct() { $config = ConfigService::make()->getConfigByGroup(7); $notifyUrl = isset($config['cregis_callback_url']['value']) ? $config['cregis_callback_url']['value'] : ''; $notifyUrl = $notifyUrl ? $notifyUrl : '/api/v1/wallet-api/cregisCallback'; self::$config = [ 'project_no' => isset($config['cregis_project_no']['value']) ? $config['cregis_project_no']['value'] : '', //商户号 'api_key' => isset($config['cregis_api_key']['value']) ? $config['cregis_api_key']['value'] : '', //apikey 'endpoint' => isset($config['cregis_endpoint']['value']) ? $config['cregis_endpoint']['value'] : '', //节点 'callUrl' => url($notifyUrl, '', true), //回调地址 'debug' => false //调试模式 ]; $this->dispatch = new CregisDispatch(self::$config); } /** * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = new static(); } return self::$instance; } /** * 获取支持的币种 * @param bool $showBalance 是否返回余额 * @return mixed */ public function supportCoins($showBalance = true) { try{ return $this->dispatch->coinslist($showBalance); } catch (\Exception $exception) { $this->error = $exception->getMessage(); return false; } } /** * HTTP 接口签名 * @param array $params 参数数组 * @return false|string */ public function makeSign(array $params) { if(empty($params)){ return false; } ksort($params); $signStr = ''; foreach ($params as $key => $val){ $signStr .= "{$key}{$val}"; } $sign = md5(self::$config['api_key'].$signStr); return $sign; } /** * 创建钱包地址 * @param string $mainCoinType * @return mixed */ public function createAddress($mainCoinType = '195') { $result = $this->dispatch->createAddress(self::$config['project_no'], $mainCoinType); $code = isset($result['code']) ? intval($result['code']) : 0; $address = isset($result['data']['address']) ? trim($result['data']['address']) : ''; if ($code == 200 && $address) { return $address; } else { RedisService::set("caches:cregisPay:createAddress:error_" . date('YmdHis'), ['mainCoinType' => $mainCoinType, 'result' => $result], 7200); return ''; } } /** * 验证钱包地址合法性 * @param $address 地址 * @param string $mainCoinType 主币 * @return mixed */ public function checkAddress($address, $mainCoinType = '195') { try { return $this->dispatch->addressLegal(self::$config['project_no'], $mainCoinType, $address); } catch (\Exception $exception) { $this->error = $exception->getMessage(); return false; } } /** * 查询地址是否存在 * @return mixed */ public function existAddress($address, $mainCoinType = '195') { return $this->dispatch->addressInner(self::$config['project_no'], $mainCoinType, $address); } /** * 提币 * @param $address 地址 * @param $amount 金额 * @param $orderNo 单号 * @param string $mainCoinType 主链编号 波场-195,solana-1000 * @param string $coinType 子链或代币合约地址 * @param string $remark 备注 * @return false */ public function withdraw($address, $amount, $orderNo, $mainCoinType = '1000', $coinType = '', $remark = '') { try { $callback = self::$config['callUrl']; $tokenAddress = ConfigService::make()->getConfigByCode('solana_usdt_token', 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'); $coinType = $coinType ? $coinType : $tokenAddress; RedisService::set("caches:cregisPay:{$orderNo}:withdraw", ['callback'=> $callback,'order_no'=>$orderNo,'amount'=>$amount,'remark'=>$remark,'mainType'=>$mainCoinType,'coinType'=>$address],7200); return $this->dispatch->payout(self::$config['project_no'], $mainCoinType . '@' . $coinType, $address, $amount, $callback, $orderNo, time(), $remark); } catch (\Exception $exception) { $this->error = $exception->getMessage(); return false; } } /** * 查询订单 * @param $orderNo 交易单号 * @return mixed */ public function queryOrder($tradeOutNo) { try { return $this->dispatch->payoutQuery(self::$config['project_no'], $tradeOutNo); } catch (\Exception $exception) { $this->error = $exception->getMessage(); return false; } } /** * 充值回调 * @return mixed */ public function callback() { $result = $this->dispatch->changeBackUrl(); RedisService::set("caches:cregisPay:recharge:callback", ['params' => request()->all(), 'result' => $result], 3600); return $result; } /** * 提现回调 * @return mixed */ public function withdrawCallBack() { $data = file_get_contents('php://input'); $params = $data?json_decode($data, true) : []; if(empty($params)){ RedisService::set("caches:cregisPay:data_".date('YmdHis'),['params'=> $params,'data'=> $data], 3600); return 'Callback data error'; } $getSign = $params['sign']; $orderNo = isset($params['third_party_id'])? trim($params['third_party_id']) : ''; $sgin = $this->dispatch->generateSign(self::$config['api_key'], $params); RedisService::set("caches:cregisPay:{$orderNo}:callback", ['params' => request()->all(), 'result' => $params], 7200); if($getSign!=$sgin){ RedisService::set("caches:cregisPay:{$orderNo}:signCheck",['params'=> request()->all(),'result'=> $params], 3600); return ''; } $payStatus = $params['status'] == 0 || $params['status'] == 6? 20 : 30; $remark = '交易回调成功'; if ($params['status'] == 2) { $remark = '签名驳回'; } else if ($params['status'] == 4) { $remark = '审批驳回'; } else if ($params['status'] == 7) { $remark = '交易失败'; } $tradeCid = isset($params['cid'])? trim($params['cid']) : ''; $txid = isset($params['txid'])? trim($params['txid']) : ''; $updateData = ['pay_status'=> $payStatus,'hash'=>$txid,'remark'=> $remark]; if($payStatus == 20){ $updateData['pay_at'] = date('Y-m-d H:i:s'); } if(!BalanceLogModel::where(['order_no'=> $orderNo,'trade_cid'=> $tradeCid,'mark'=>1])->update($updateData)){ RedisService::set("caches:cregisPay:{$orderNo}:failed", ['params' => request()->all(),'data'=>$updateData, 'result' => $params], 7200); $this->error = 2034; return ''; } RedisService::set("caches:cregisPay:{$orderNo}:success", ['params' => request()->all(),'data'=>$updateData, 'result' => $params], 7200); return 'success'; } /** * 回调处理 * @param $params */ public function catchNotify($params) { RedisService::set('caches:cregisPay:notify', $params); } }