Winnet获取网页HTML内容-Code

bool loadHtmlFile(const CString& strUrl, CString& strHtml)
 {
  bool bRet = false;
  CInternetSession sess;//建立会话
  sess.SetOption(INTERNET_OPTION_CONNECT_TIME, 10*1000, NULL);//似乎不起作用,微软SDK的一个bug

  CHttpFile* fileGet = 0;
  InternetParam param;
  param.pSession = &sess;
  param.pHttpFile = &fileGet;
  param.strUrl = strUrl;
  HANDLE hThread = ::CreateThread(NULL, 0, openUrlProc, (LPVOID)&param, NULL, NULL);//自己开线程处理超时
  DWORD dwTimeOut = 10*1000;
  if (::WaitForSingleObject(hThread, dwTimeOut) == WAIT_TIMEOUT)
  {
   sess.Close();
   return false;
  }
  fileGet = *(param.pHttpFile);
  if(fileGet)
  {
   DWORD dwStatus;
   DWORD dwBuffLen = sizeof(dwStatus);
   BOOL bSuccess = fileGet->QueryInfo(
    HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,
    &dwStatus, &dwBuffLen);
   if( bSuccess && dwStatus>= 200 && dwStatus<300 )
   {
    const int ContentSize = 1024000;//maximin size of text form html file.
    char* mbbuf = new char[ContentSize];
    int nRead = fileGet->Read(mbbuf, ContentSize-1);
    if(nRead > 0 && nRead < ContentSize)
    {
     mbbuf[nRead] = 0;
     int nWordCount = MultiByteToWideChar(CP_ACP, NULL, mbbuf, nRead, NULL, NULL);
     if(nWordCount > 0)
     {
      wchar_t* wstrUnicode = new wchar_t[nWordCount+1];
      wstrUnicode[nWordCount] = 0;
      MultiByteToWideChar(CP_ACP, NULL, mbbuf, nRead, wstrUnicode, nWordCount+1);
      strHtml = wstrUnicode;
      delete[] wstrUnicode;
      bRet = true;
     }
    }
    delete[] mbbuf;
   }
   fileGet->Close();
   delete fileGet;
  }
  sess.Close();
  return bRet;
 } 

UNIX主机和WINDOWS主机的回车问题

CString unixRetToWindowRet(const CString& strTxt)//
 {
  if(strTxt.GetLength() > 0)
  {
   wchar_t* buf = new wchar_t[strTxt.GetLength()*2+1];
   const wchar_t* pSrc = (LPCTSTR)strTxt;
   int nCount = 0;  
   if(pSrc[0] == '/n')
    buf[nCount++] = '/r';
   buf[nCount++] = pSrc[0];
   for(int i = 1; i < strTxt.GetLength(); i++)
   {
    if(*(pSrc+i) == '/n' && *(pSrc+i-1) != '/r')
     buf[nCount++] = '/r';
    buf[nCount++] = *(pSrc+i);
   }
   buf[nCount++] = 0;
   return buf;
  }
  return CString();
 }

我在代码片段中上传了代码 , 这是我的tp5 的抽奖 满多少人自动触发的抽奖接口, 我现在要在后台这个抽奖活动设置一个或者多个内定的手机号 , 所以同步也要修改这个接口的内定中奖人逻辑 , 帮我写出 并且不要超出中奖内定的人数哦 , 如果当前$user['mobile']是内定人之一 到时候最后一个人参与后 就可以触发优先内定人为中奖的了 如果没有设置内定 那就是随机 这是我当前的代码: // 参与抽奖 public function start_skill($data=[],$user=[]) { $activityId = $data['id']; //用于测试 // $delReids = self::resetLotteryRedis($activityId); // echo '清空活动的redis 成功';die; $userId = $user['id']; // 获取当前用户ID // 验证活动 $activity = Db::name('goods_activity') ->where('id', $activityId) ->where('type', 1) // 抽奖类型 ->where('status', 1) // 进行中 ->where('edate', '>=', time()) // 未结束 ->lock(true) // 加行锁防止并发修改 ->find(); if(!$activity){ return ApiReturn::r(0, [], '活动不存在或已结束'); } // 检查活动是否已开始 if ($activity['sdate'] > time()) { return ApiReturn::r(0, [], '活动尚未开始'); } // Redis防并发锁 $lockKey = "lottery:lock:{$activityId}:{$userId}"; $joinKey = "lottery:joined:{$activityId}:{$userId}"; $redis = \app\common\model\Redis::handler(); $shouldSetJoinKey = false; Db::startTrans(); try { // 获取分布式锁 if(!$redis->set($lockKey, 1, ['nx', 'ex' => 5])){ exception('操作过于频繁,请稍后再试'); } // 1.检查是否已参与 (使用Redis缓存提高性能) // dump($redis->get($joinKey));die; // $ttl = $redis->ttl($joinKey); // 检查是否已参与时,优先查Redis,但最终以数据库为准 if ($redis->get($joinKey)) { $hasJoined = Db::name('goods_activity_skill_record') ->where(['activity_id' => $activityId, 'user_id' => $userId]) ->count(); if ($hasJoined > 0) { exception('您已参与过该活动~'); } else { // 修复Redis脏数据 $redis->del($joinKey); } }else{ $hasJoined = Db::name('goods_activity_skill_record') ->where(['activity_id' => $activityId, 'user_id' => $userId]) ->count(); if ($hasJoined > 0) { exception('您已参与过该活动!'); } } // Redis原子计数 $countKey = "lottery:count:{$activityId}"; $current = $redis->incr($countKey); // dump($current);die; // 首次设置过期时间 if ($current == 1) { $redis->expire($countKey, $activity['edate'] - time()); // 设置到活动结束 } // 获取奖品列表 $draw_goods = Db::name('goods_activity_details')->alias('d') ->join('goods g','g.id = d.goods_id') ->where('d.activity_id', $activityId) ->field('d.goods_id,d.join_number,g.name as goods_name,g.thumb as goods_thumb') ->find(); if(!$draw_goods){ exception('活动奖品不存在'); } // 检查人数限制 Jlog('检查人数限制',$current.'====='.$draw_goods['join_number'],'skill_draw'); if($current > $draw_goods['join_number']){ $redis->decr($countKey); // 回滚计数 exception('活动人数已满,已自动开奖'); } // 记录参与信息 $recordId = Db::name('goods_activity_skill_record')->insertGetId([ 'activity_id' => $activityId, 'user_id' => $userId, 'create_time' => time(), 'is_winner' => 0, // 'verify_code' => '' 'ip' => request()->ip() // 记录用户IP ]); if (!$recordId) { $redis->decr($countKey); // 回滚计数 exception('参与失败,请重试'); } // 修改这里:只有当数据库插入成功时才设置Redis标记 if ($recordId) { $shouldSetJoinKey = true; } // 人数达标触发开奖 if($current == $draw_goods['join_number']){ $drawResult = self::syncDraw($activityId,$userId,$draw_goods['join_number'],$activity['icon']);//立即执行开奖 非队列开奖 Jlog('事务提交20', '成功'.$drawResult, 'skill_draw'); if ($drawResult['code'] == 1) { $is_draw_user = 1;//中奖者提示 Db::commit(); Jlog('事务提交21', '成功'.$recordId, 'skill_draw'); }else{ exception($drawResult['msg']); } }else{ $is_draw_user = 0;//非中奖者提示 Db::commit(); Jlog('事务提交1', '成功'.$recordId, 'skill_draw'); } } catch (\Exception $e) { // 确保不设置Redis标记 $shouldSetJoinKey = false; // 记录错误日志 // Log::error("抽奖参与失败: ".$e->getMessage()); Jlog('抽奖参与失败',$e->getMessage(),'skill_draw'); Db::rollback(); return ApiReturn::r(0, [], $e->getMessage()); } finally { $redis->del($lockKey); // 释放锁 } // 只有事务成功提交后才设置Redis标记 缓存参与状态 if ($shouldSetJoinKey) { Jlog('抽奖参与走完了',$joinKey,'skill_draw'); $redis->setex($joinKey, 3600, 1); } if($is_draw_user == 1){ return ApiReturn::r(1, ['is_draw'=>1],'参与成功,活动即将自动开奖'); }else{ return ApiReturn::r(1, ['is_draw'=>0],'参与成功'); } } // 触发自动开奖 /** * 同步开奖方法 * @param int $activityId 活动ID * @return array|bool 中奖用户ID数组或false */ private function syncDraw($activityId, $userId, $joinNumber, $activity_thumb) { $redis = \app\common\model\Redis::handler(); $lockKey = "lottery:drawing:{$activityId}"; // 获取分布式锁(防止并发开奖) if (!$redis->set($lockKey, 1, ['nx', 'ex' => 30])) { return ['code' => 0, 'msg' => '网络拥堵,请稍后重试']; } Db::startTrans(); try { // 1. 获取活动信息(加行锁) $activity = Db::name('goods_activity') ->where('id', $activityId) ->lock(true) ->find(); if (!$activity || $activity['status'] != 1) { throw new \Exception('活动信息错误'); } // 2. 抽奖逻辑 目前是随机 最后一个人抽奖就开奖 , 中奖是谁 应该自定义 后续测试的时候 $winnerId = Db::name('goods_activity_skill_record') ->where('activity_id', $activityId) ->where('is_winner', 0) ->orderRaw('RAND()') ->value('user_id'); if (empty($winnerId)) { throw new \Exception('暂无有效参与者'); } // 3. 更新中奖记录和活动状态 $code = rand(1000, 9999); Db::name('goods_activity_skill_record') ->where('activity_id', $activityId) ->where('user_id', $winnerId) ->update([ 'is_winner' => 1, 'verify_code' => $code, 'win_time' => time() ]); Db::name('goods_activity') ->where('id', $activityId) ->update([ 'draw_status' => 1,//0进行中 1人满自动开奖 'draw_user_id' => $userId,//触发活动开奖的用户id 'draw_time' => time() ]); Jlog('开奖通知参数',[$winnerId, $activityId,$activity_thumb],'skill_draw'); // 5. 异步通知 怎么通知给大哥了??? $sendres = self::asyncNotifyWinners($winnerId, $activityId,$activity_thumb); if(!$sendres){ exception('通知中奖用户error'); } Db::commit(); return ['code' => 1, 'msg' => '已成功开奖']; } catch (\Exception $e) { Db::rollback(); Jlog('开奖失败', $e->getMessage(), 'skill_draw'); return ['code' => 0, 'msg' => $e->getMessage()]; } finally { $redis->del($lockKey); // 确保锁释放 } } /** * 异步通知中奖者(模拟异步) */ private function asyncNotifyWinners($winnerId, $activityId,$activity_thumb) { //通知中奖者 目前没通知别人 $r = SystemMessage::send_msg( $winnerId, lang('活动消息'), '您参与的抽奖活动已开奖,请前往[抽奖专区-我参与的]查看', 1, 3, 1, $activity_thumb, '/pages/activity/seckill/seckill-detail/index?id='.$activityId ); return $r; }
10-23
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值