|
|
@@ -236,6 +236,142 @@ class CollectService extends BaseService
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @description: 处理指定会员待归集记录,会执行链上归集
|
|
|
+ * @param {*} $memberId
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function syncCollectStayByMember($memberId)
|
|
|
+ {
|
|
|
+ $result = [
|
|
|
+ 'member_id' => $memberId,
|
|
|
+ 'threshold' => self::$THRESHOLD,
|
|
|
+ 'from_address' => null,
|
|
|
+ 'to_address' => null,
|
|
|
+ 'pending_count' => 0,
|
|
|
+ 'handled_count' => 0,
|
|
|
+ 'success_count' => 0,
|
|
|
+ 'fail_count' => 0,
|
|
|
+ 'items' => [],
|
|
|
+ ];
|
|
|
+
|
|
|
+ $walletInfo = WalletService::findOne(['member_id' => $memberId, 'coin' => 'USDT']);
|
|
|
+ if (empty($walletInfo) || empty($walletInfo->address)) {
|
|
|
+ $result['message'] = '未找到该用户的USDT钱包地址';
|
|
|
+ Log::warning('syncCollectStayByMember skipped: wallet missing', [
|
|
|
+ 'member_id' => $memberId,
|
|
|
+ ]);
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
+ $result['from_address'] = $walletInfo->address;
|
|
|
+
|
|
|
+ $to_address = self::getUsdtAddress();
|
|
|
+ $trx_private_key = self::getTrxPrivateKey();
|
|
|
+ $result['to_address'] = $to_address;
|
|
|
+
|
|
|
+ Log::info('syncCollectStayByMember start', [
|
|
|
+ 'member_id' => $memberId,
|
|
|
+ 'from_address' => $walletInfo->address,
|
|
|
+ 'threshold' => self::$THRESHOLD,
|
|
|
+ 'to_address' => $to_address,
|
|
|
+ 'has_trx_private_key' => !empty($trx_private_key),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ if (!$to_address || !$trx_private_key) {
|
|
|
+ $result['message'] = '归集配置不完整';
|
|
|
+ Log::warning('syncCollectStayByMember skipped: missing config', [
|
|
|
+ 'member_id' => $memberId,
|
|
|
+ 'to_address' => $to_address,
|
|
|
+ 'has_trx_private_key' => !empty($trx_private_key),
|
|
|
+ ]);
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
+ $list = self::findAll([
|
|
|
+ 'status' => self::model()::STATUS_STAY,
|
|
|
+ 'amount' => self::$THRESHOLD,
|
|
|
+ 'from_address' => $walletInfo->address,
|
|
|
+ ]);
|
|
|
+ $result['pending_count'] = $list->count();
|
|
|
+
|
|
|
+ if ($list->isEmpty()) {
|
|
|
+ $result['message'] = '该用户没有待归集记录';
|
|
|
+ Log::info('syncCollectStayByMember finished: no pending collects', $result);
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($list as $v) {
|
|
|
+ $item = [
|
|
|
+ 'id' => $v['id'],
|
|
|
+ 'from_address' => $v['from_address'],
|
|
|
+ 'amount' => $v['amount'],
|
|
|
+ 'status' => 'pending',
|
|
|
+ ];
|
|
|
+ $data = [];
|
|
|
+ $wallets = WalletService::findOne(['address' => $v['from_address']]);
|
|
|
+
|
|
|
+ if (empty($wallets) || empty($wallets['private_key'])) {
|
|
|
+ $item['status'] = 'wallet_not_found';
|
|
|
+ $item['error'] = '未找到归集钱包私钥';
|
|
|
+ $data['remark'] = $item['error'];
|
|
|
+ $data['updated_at'] = now();
|
|
|
+ self::model()::where(self::getWhere(['id' => $v['id']]))->update($data);
|
|
|
+ $result['fail_count']++;
|
|
|
+ $result['handled_count']++;
|
|
|
+ $result['items'][] = $item;
|
|
|
+ Log::warning('syncCollectStayByMember wallet missing', $item + ['member_id' => $memberId]);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $privateKey = $wallets['private_key'];
|
|
|
+ $trxBalance = TronHelper::getTrxBalance($v['from_address']);
|
|
|
+ $item['trx_balance'] = $trxBalance;
|
|
|
+
|
|
|
+ if ($trxBalance < 10) {
|
|
|
+ $trxResult = TronHelper::sendTrx($trx_private_key, $v['from_address'], 10);
|
|
|
+ $item['trx_topup_result'] = $trxResult;
|
|
|
+ Log::info('syncCollectStayByMember topup trx', [
|
|
|
+ 'member_id' => $memberId,
|
|
|
+ 'from_address' => $v['from_address'],
|
|
|
+ 'trx_balance' => $trxBalance,
|
|
|
+ 'result' => $trxResult,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $transferResult = TronHelper::transferUSDT($privateKey, $to_address, $v['amount']);
|
|
|
+ $item['transfer_result'] = $transferResult;
|
|
|
+
|
|
|
+ $data['to_address'] = $to_address;
|
|
|
+ if (is_array($transferResult) && !empty($transferResult['success'])) {
|
|
|
+ $data['txid'] = $transferResult['txid'] ?? '';
|
|
|
+ $data['remark'] = 'success';
|
|
|
+ $data['status'] = self::model()::STATUS_START;
|
|
|
+ $item['status'] = 'success';
|
|
|
+ $item['txid'] = $data['txid'];
|
|
|
+ $result['success_count']++;
|
|
|
+ Log::info('syncCollectStayByMember transfer success', $item + ['member_id' => $memberId]);
|
|
|
+ } else {
|
|
|
+ $error = is_array($transferResult)
|
|
|
+ ? ($transferResult['error'] ?? 'USDT归集失败')
|
|
|
+ : (is_string($transferResult) ? $transferResult : 'USDT归集失败');
|
|
|
+ $data['remark'] = $error;
|
|
|
+ $item['status'] = 'failed';
|
|
|
+ $item['error'] = $error;
|
|
|
+ $result['fail_count']++;
|
|
|
+ Log::warning('syncCollectStayByMember transfer failed', $item + ['member_id' => $memberId]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $data['updated_at'] = now();
|
|
|
+ self::model()::where(self::getWhere(['id' => $v['id']]))->update($data);
|
|
|
+ $result['handled_count']++;
|
|
|
+ $result['items'][] = $item;
|
|
|
+ }
|
|
|
+
|
|
|
+ Log::info('syncCollectStayByMember finished', $result);
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @description: 处理待归集的
|
|
|
* @return {*}
|