فهرست منبع

wesmiler 报恩寺项目

wesmiler 4 سال پیش
والد
کامیت
a15a50798f

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 29 - 11
app/Http/Controllers/Api/TestController.php


+ 15 - 12
app/Http/Controllers/Api/v1/NotifyController.php

@@ -34,24 +34,26 @@ class NotifyController extends BaseController
      * 支付回调
      */
     public function pay($scene){
-        $postStr = file_get_contents('php://input');
-        RedisService::set('caches:payments:'.$scene.':result'.date('YmdHis'), ['result'=> request()->all(),'post'=> $_POST,'get'=> $_GET,'input'=> $postStr], 7200);
-        if(empty($scene)){
-            return message('参数错误回调失败', false);
+        $postData = request()->all();
+        RedisService::set('caches:payments:'.$scene.':result'.date('YmdHis'), ['result'=> request()->all()], 7200);
+        $postData = isset($postData['resource'])? $postData['resource'] : [];
+        if(empty($scene) || empty($postData)){
+            return NotifyService::make()->rebackMsg('回调参数错误');
         }
 
+        // 解密
+        $ciphertext = isset($postData['ciphertext'])? $postData['ciphertext'] : '';
+        if(empty($ciphertext)){
+            return NotifyService::make()->rebackMsg('解密数据不存在');
+        }
 
-        $postData =$postStr? json_decode($postStr, true) : [];
+        $postData = WechatService::decryptNotifyData($postData);
         $outTradeNo = isset($postData['out_trade_no']) ? $postData['out_trade_no'] : '';
         if(empty($postData) || empty($outTradeNo)){
-            //禁止引用外部xml实体
-            libxml_disable_entity_loader(true);
-            $postData = (array)(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA));
+            return NotifyService::make()->rebackMsg('获取解密数据失败');
         }
 
-        $outTradeNo = isset($postData['out_trade_no']) ? $postData['out_trade_no'] : '';
-        $taskNo = $outTradeNo ? $outTradeNo : date('YmdHis');
-        RedisService::set('caches:payments:'.$scene.':result_'.$taskNo, ['result'=> $postData], 7200);
+        RedisService::set('caches:payments:'.$scene.':result_'.$outTradeNo, ['result'=> $postData], 7200);
         if (WechatService::checkJsapiNotify($postData) === true) {
             switch($scene){
                 case 'index': // 供灯订单
@@ -64,6 +66,7 @@ class NotifyController extends BaseController
             }
         }
 
-        return message('回调失败', false);
+        return NotifyService::make()->rebackMsg('回调失败');
     }
+
 }

+ 12 - 0
app/Services/ConfigService.php

@@ -22,6 +22,7 @@ use App\Models\ConfigModel;
  */
 class ConfigService extends BaseService
 {
+    protected static $instance = null;
     /**
      * 构造函数
      * @author wesmiler
@@ -34,6 +35,17 @@ class ConfigService extends BaseService
     }
 
     /**
+     * 静态入口
+     * @return ConfigService|null
+     */
+    public static function make(){
+        if(!self::$instance){
+            self::$instance = new ConfigService();
+        }
+        return self::$instance;
+    }
+
+    /**
      * 获取配置列表
      * @return array
      * @since 2020/11/11

+ 106 - 0
app/Services/DevicesService.php

@@ -12,6 +12,7 @@
 namespace App\Services;
 
 use App\Models\DevicesModel;
+use App\Models\GongdengOrderModel;
 
 /**
  * 供灯设备管理-服务类
@@ -22,6 +23,7 @@ use App\Models\DevicesModel;
  */
 class DevicesService extends BaseService
 {
+    protected static $instance=null;
     /**
      * 构造函数
      * @author wesmiler
@@ -34,6 +36,18 @@ class DevicesService extends BaseService
     }
 
     /**
+     * 静态入口
+     * @return DevicesService|null
+     */
+    public static function make(){
+        if(!self::$instance){
+            self::$instance = new DevicesService();
+        }
+
+        return self::$instance;
+    }
+
+    /**
      * 获取友链列表
      * @return array
      * @since 2020/11/11
@@ -72,4 +86,96 @@ class DevicesService extends BaseService
         return parent::edit($data); // TODO: Change the autogenerated stub
     }
 
+    /**
+     * 获取设备端口
+     * @return array
+     */
+    public function getDevice(){
+        $datas = $this->model::where(['status'=> 1])->orderRaw("rand()")->first();
+        $datas = $datas? $datas->toArray() : [];
+        return $datas;
+    }
+
+    /**
+     * 获取可用设备号
+     * @return array|false|mixed
+     */
+    public function getDeviceNums($deviceInfo){
+        $deviceCode = isset($deviceInfo['code'])? $deviceInfo['code'] : '';
+        if(empty($deviceCode)){
+            return false;
+        }
+
+        if(!$deviceInfo || $deviceInfo['start_num'] >= $deviceInfo['end_num']){
+            return false;
+        }
+
+        $cacheKey = "caches:devices:nums_{$deviceCode}";
+        $datas = RedisService::get($cacheKey);
+        if($datas){
+            shuffle($datas);
+            $datas = array_values($datas);
+            return $datas;
+        }
+
+        $deviceNums = range($deviceInfo->start_num, $deviceInfo->end_num);
+        $datas = GongdengOrderModel::where(['status'=> 2, 'lamp_status'=> 2])->pluck('device_num');
+        $datas = $datas? $datas->toArray() : [];
+        if($datas && $deviceNums){
+            $datas = array_diff($deviceNums, $datas);
+            if($datas){
+                RedisService::set($cacheKey, $datas, rand(3,5));
+            }
+        }
+
+        return $datas;
+    }
+
+    public function catchLamp($orderSn){
+        if(empty($orderSn)){
+            return false;
+        }
+
+        // 获取可用设备
+        $errorKey = "caches:lamps:{$orderSn}";
+        $deviceInfo = $this->getDevice();
+        $deviceCode = isset($deviceInfo['code'])? $deviceInfo['code'] : '';
+        $startNum = isset($deviceInfo['start_num'])? $deviceInfo['start_num'] : 0;
+        $endNum = isset($deviceInfo['end_num'])? $deviceInfo['end_num'] : 0;
+        $port = isset($deviceInfo['port'])? $deviceInfo['port'] : 0;
+        if(empty($deviceInfo) || empty($deviceCode) || ($startNum >= $endNum) || !$port){
+            RedisService::set("{$errorKey}:error_check", ['info'=> $deviceInfo], 3600);
+            return false;
+        }
+
+        // 获取可用设备号
+        $deviceNums = DevicesService::make()->getDeviceNums($deviceInfo);
+        $deviceLampNo = $deviceNums? $deviceNums[0] : 0;
+        if(empty($deviceLampNo)){
+            RedisService::set("{$errorKey}:error_device", ['info'=> $deviceInfo,'nums'=> $deviceNums], 3600);
+            return false;
+        }
+
+        // 亮灯处理
+        unset($deviceNums[0]);
+        RedisService::set("caches:devices:nums_{$deviceCode}", $deviceNums, rand(3,5));
+        $colors = ['黄','红','绿','白'];
+        shuffle($colors);
+        $data = [
+            'CommandType'=> '', // 执行命令方式:
+            'MD'=> $deviceCode, // 机器号设备号
+            'MDPORT'=> $port,
+            'LEDID'=> $deviceLampNo,
+            'Color'=> $colors[0],
+        ];
+
+        // 调用亮灯接口处理
+        $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url');
+        RedisService::set($errorKey.':request', ['url'=> $apiUrl,'data'=> $data], 3600);
+        $result = httpRequest($apiUrl, $data);
+        RedisService::set($errorKey.':result', $result, 3600);
+
+        // 更新灯状态
+        
+    }
 }

+ 24 - 8
app/Services/NotifyService.php

@@ -67,21 +67,20 @@ class NotifyService extends BaseService
         $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : 0;
         $userId = isset($orderInfo['user_id']) ? intval($orderInfo['user_id']) : 0;
         if (empty($orderInfo) || $userId<=0) {
-            NotifyService::rebackOk();
-            return false;
+            return NotifyService::rebackMsg('订单数据不存在', 'success');
         }
 
         // 订单用户
         $memberInfo = MemberModel::where(['id'=> $userId])->select(['id','openid','nickname','coupon','status'])->first();
         if(!$memberInfo){
             NotifyService::rebackOk();
-            return false;
+            return NotifyService::rebackMsg('订单用户不存在', 'success');
         }
 
         // 验证订单状态是否可处理
         if ($orderStatus != 1) {
             NotifyService::rebackOk();
-            return false;
+            return NotifyService::rebackMsg('订单已处理', 'success');
         }
 
         // 验证订单金额是否正确
@@ -93,7 +92,7 @@ class NotifyService extends BaseService
         if (!$payDebug && intval($orderAmount * 100) != intval($payMoney)) {
             RedisService::set($errorKey.':error_money',['notify'=> $notifyData, 'error'=> '实付金额与订单金额不一致','order'=> $orderInfo
             ], 3600);
-            return false;
+            return NotifyService::rebackMsg('实付金额与订单金额不一致', 'error');
         }
 
         // 更新订单数据
@@ -102,7 +101,7 @@ class NotifyService extends BaseService
             RedisService::set($errorKey.':error_update',['notify'=> $notifyData, 'error'=> '更新订单信息失败','order'=> $orderInfo
             ], 3600);
             DB::rollBack();
-            return false;
+            return NotifyService::rebackMsg('更新订单数据失败', 'error');
         }
 
         // 处理支付明细
@@ -122,10 +121,17 @@ class NotifyService extends BaseService
             RedisService::set($errorKey.':error_account',['notify'=> $notifyData, 'error'=> '处理交易明细失败','order'=> $orderInfo
             ], 3600);
             DB::rollBack();
-            return false;
+            return NotifyService::rebackMsg('处理交易明细失败', 'error');
         }
 
-        // 开灯处理
+        DB::commit();
+
+        // 开灯处理,续费不处理
+        $buyType = isset($orderInfo['buy_type'])? $orderInfo['buy_type'] : 0;
+        if($buyType == 1){
+
+
+        }
 
         // 消息处理
 
@@ -138,4 +144,14 @@ class NotifyService extends BaseService
         echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
         exit;
     }
+
+    /**
+     * V3支付回调应答
+     * @param $code
+     * @param string $msg
+     * @return false|string
+     */
+    public static function rebackMsg($msg='失败', $code='error'){
+        return json_encode(['code'=> $code, 'message'=> $msg]);
+    }
 }

+ 22 - 2
app/Services/WechatService.php

@@ -815,11 +815,31 @@ class WechatService extends BaseService
     }
 
     /**
+     * 回调数据解密
+     * @param $notifyData 回调数据对象
+     * @return false|string
+     * @throws \SodiumException
+     */
+    public static function decryptNotifyData($notifyData){
+        $md5Key = 'ThgVdjd0YFzX5QYMYkLbNV4bkHPEEJTN';
+//        $md5Key = WechatService::getConfigs('wx_pay_key');
+        $ciphertext = isset($notifyData['ciphertext'])? $notifyData['ciphertext'] : '';
+        $associatedData = isset($notifyData['associated_data'])? $notifyData['associated_data'] : '';
+        $nonce = isset($notifyData['nonce'])? $notifyData['nonce'] : '';
+        var_dump($md5Key);
+        var_dump($ciphertext);
+        var_dump($associatedData);
+        var_dump($nonce);
+        $ciphertext = base64_decode($ciphertext);
+        return sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonce, $md5Key);
+    }
+
+    /**
      * 验证JSAPI回调
      * @param $notifyData
      * @return array|bool
      */
-    public static function checkJsapiNotify($notifyData)
+    public static function checkJsapiNotify($notifyData, $version='v2')
     {
         if (empty($notifyData)) {
             return ['code' => 'error', 'message' => 'parse xml error'];
@@ -839,7 +859,7 @@ class WechatService extends BaseService
 
         // 验证签名
         unset($notifyData['sign']);
-        $sign = WechatService::getPaySign($notifyData);
+        $sign = $version == 'v3'? WechatService::getPaySignV3($notifyData) : WechatService::getPaySign($notifyData);
         if ($nofitySign == $sign) {
             echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
             return true;