queryFundAccount(); \Log::info('queryFundAccount_res:'.$fund_account_res->alipay_fund_account_query_response->available_amount); \Log::info(json_encode($fund_account_res)); //{"alipay_fund_account_query_response":{"code":"10000","msg":"Success","available_amount":"499.70","freeze_amount":"0.00"},"alipay_cert_sn":"c0a0f43f741ae05c456b45aa20c231e4","sign":"BFQQ8Qqj2sT82vZAvPUlxfXrETSt9Mwhfche8ao5DRJNNP4f9cDPafDMeeixhtbeqlEHtGpjCTW\/vcaCk+UdKs7pZTCv17MZyzS1V1t9G1a7Y5hSbqHBNldTFrwsB\/yvFNbk2MGNd\/cX5Yp1kWjljPE8UEfSzpTNA3IQip8fNuzkJQbGomqFZjPbhD8pMcOvhKWRguImMc0fxOiWXnV0lFkfjtN5zXZNeZZhalskfDL9lnq0mn3aEamNZM8lya6nor7D0o0k2K\/ZuDqoX+clOA580LD6\/zu8Il+ZwSWE37RY7oCah7ggxbuSwKS0t3kwHwhiLcKm\/Ynzs1zT4aX4kw=="} // 钱不够直接返回 $before_limit_minute = 120; $toTransUserWithdrawCashes = WithdrawCashService::getToTransUserWithdrawCashes($before_limit_minute); \Log::info('trans_fund_toTransUserWithdrawCashes,count:'.count($toTransUserWithdrawCashes)); if(!empty($toTransUserWithdrawCashes)){ foreach($toTransUserWithdrawCashes as $toTransUserWithdrawCashe){ $redis_lock_key = 'trans_fund_lock:'.$toTransUserWithdrawCashe['id']; try{ if(Redis::get($redis_lock_key)){ \Log::info('trans_fund_one_lock_return:'.json_encode($toTransUserWithdrawCashe)); continue; } # 加redis锁,防止并发,有错误就改状态为待打款 Redis::set($redis_lock_key,date('Y-m-d H:i:s')); \Log::info('trans_fund_one_toTransUserWithdrawCashes:'.$toTransUserWithdrawCashe['uid']); $risk_manage_param = [ 'uid'=>$toTransUserWithdrawCashe['uid'], 'distribution_channel_id'=>$toTransUserWithdrawCashe['distribution_channel_id'], 'alipay_username'=>$toTransUserWithdrawCashe['alipay_username'], 'alipay_account'=>$toTransUserWithdrawCashe['alipay_account'], 'amount'=>$toTransUserWithdrawCashe['amount'], ]; // 风控策略 $risk_check = $this->risk_manage($risk_manage_param); if($risk_check['code'] == 0){ \Log::info('withdraw_risk_manage_error:'.$toTransUserWithdrawCashe['uid']); $toTransUserWithdrawCashe['status'] = '打款失败'; $toTransUserWithdrawCashe['trans_fund_result'] = '触发风控策略:'.$risk_check['msg']; $toTransUserWithdrawCashe->save(); # 删锁 Redis::del($redis_lock_key); continue; } // FIXME 测试期间,统一1分提现 // $toTransUserWithdrawCashe['amount'] = 0.1; $trans_param = [ 'out_biz_no'=>generateOrderSn('tf-'),// 平台订单号 'account'=>$toTransUserWithdrawCashe['alipay_account'], 'account_name'=>$toTransUserWithdrawCashe['alipay_username'], 'trans_amount'=>$toTransUserWithdrawCashe['amount'], 'order_title'=>'火猫小说', 'remark'=>'收益提现', ]; \Log::info('start_transfund:'.json_encode($trans_param)); // continue; // 执行转账 ,记录下转账的结果 $transFund_res = $alipay->transFund($trans_param); // {"alipay_fund_trans_uni_transfer_response":{"code":"10000","msg":"Success","order_id":"20230529020070011500080081135133","out_biz_no":"tf-2023052917470116853536215518734","pay_fund_order_id":"20230529020070011500080081135133","status":"SUCCESS","trans_date":"2023-05-29 17:47:02"},"alipay_cert_sn":"c0a0f43f741ae05c456b45aa20c231e4","sign":"NP6p5hn9NLsED2MdaaxnD3HXtyE2QSGo3RkV7kOwnoHEK6GXwhjLiW9cgBfk63VxCTrtKy1\/AoKq8PzPNIc1CJs4XHRfeIgh1ptkDVv+AfTNIpgBjrXB8ijEHukfEkdOEeRNHYQ3wrBt7sfObFek11ospCktxXutDv2mLy3QOv4AgZD5DF0CDyfRrTYMuOvL2l5zNexTrq5XFwa4sb1QRtVP0Pj25T0Sn\/Sz6O0Y3sEv1woHP3jPdqiSS1E6T\/fdnSF5VYc2syzL4mnaEf0aLDnHxwi8NnW8NqDRdB7PrnwOjsTwsktvkvKvnsfDtjPG4AgT3S\/EE6i1GFfl1w7oLA=="} \Log::info('transFund_res'); \Log::info(json_encode($transFund_res)); if(isset($transFund_res->alipay_fund_trans_uni_transfer_response) && $transFund_res->alipay_fund_trans_uni_transfer_response->code=='10000'){ $toTransUserWithdrawCashe['status'] = '系统已打款'; }else{ $toTransUserWithdrawCashe['status'] = '打款失败'; } $toTransUserWithdrawCashe['trans_time'] = date('Y-m-d H:i:s'); $toTransUserWithdrawCashe['trans_trade_no'] = $trans_param['out_biz_no']; $toTransUserWithdrawCashe['tiktok_trade_no'] = isset($transFund_res->alipay_fund_trans_uni_transfer_response->order_id)?$transFund_res->alipay_fund_trans_uni_transfer_response->order_id:''; $toTransUserWithdrawCashe['trans_fund_result'] = json_encode($transFund_res,JSON_UNESCAPED_UNICODE); $toTransUserWithdrawCashe->save(); // TODO 如果打款成功,做钉钉通知 }catch(\Exception $e){ \Log::info('trans_ept:'.$e); # 删锁 Redis::del($redis_lock_key); } // 重要,防止上一个循环数据库没执行成功,影响风控判断 sleep(5); } } // else{ \Log::info('trans_fund_toTransUserWithdrawCashes,nothing todo:'); } } // 风控 public function risk_manage($param){ $result = ['code'=>1,'msg'=>'']; \Log::info('risk_manage_start:'.json_encode($param)); // 账户不允许空 if(empty($param['alipay_username']) || empty($param['alipay_account'])){ \Log::info('withdraw_account_error:'.json_encode($param)); $result['code'] = 0; $result['msg'] = '支付宝姓名或者账户是空'; return $result; } // TODO 金额不能超过100,待定 $limit_amount = 1; if($param['amount'] > $limit_amount){ \Log::info('withdraw_amount_error:'.json_encode($param).' account:'.$param['alipay_account']); $result['code'] = 0; $result['msg'] = '打款金额超过:'.$limit_amount; return $result; } // 提现账户角度:今天提现过2次,则不能再提,防止爆破改账号风险 $query_data = [ 'alipay_account'=>$param['alipay_account'] ]; $user_withdraw_cashes = WithdrawCashService::getUserWithdrawCashes($query_data); \Log::info('$user_withdraw_cashes_check_alipay_account_acount:'); \Log::info($user_withdraw_cashes); $limit_trans_num = 1; if(count($user_withdraw_cashes) >=$limit_trans_num){ \Log::info('withdraw_account_today_has_over_limit_error:'.$param['alipay_account'].' count:'.count($user_withdraw_cashes)); $result['code'] = 0; $result['msg'] = '支付宝账户'.$param['alipay_account'].'今日打款超过次数:'.$limit_trans_num; return $result; } // uid角度:今天1个uid提现过1次,则不能再提 $query_data = [ 'uid'=>$param['uid'] ]; $user_withdraw_cashes = WithdrawCashService::getUserWithdrawCashes($query_data); \Log::info('$user_withdraw_cashes_check_user_count:'); \Log::info($user_withdraw_cashes); if(count($user_withdraw_cashes) >=1){ \Log::info('withdraw_uid_today_has_over_limit_error:'.$param['uid'].' count:'.count($user_withdraw_cashes)); $result['code'] = 0; $result['msg'] = '用户id:'.$param['uid'].'今日打款超过次数:'.$limit_trans_num; return $result; } return $result; } }