Forráskód Böngészése

wesmiler 报恩寺项目

wesmiler 4 éve
szülő
commit
7c57596672

+ 15 - 2
app/Http/Controllers/Api/v1/GongdengController.php

@@ -3,7 +3,8 @@
 namespace App\Http\Controllers\Api\v1;
 
 use App\Http\Controllers\Api\BaseController;
-use App\Models\GongdengOrderModel;
+use App\Http\Validator\GongdengValidator;
+use App\Services\GongdengOrderService;
 use App\Services\GongdengFoxiangService;
 use App\Services\LampMealsService;
 
@@ -26,7 +27,7 @@ class GongdengController extends BaseController
     {
         parent::__construct();
 
-        $this->service = new GongdengOrderModel();
+        $this->service = new GongdengOrderService();
         $this->fxService = new GongdengFoxiangService();
         $this->mealService = new LampMealsService();
     }
@@ -62,4 +63,16 @@ class GongdengController extends BaseController
     public function gdList(){
         return $this->service->getList();
     }
+
+    /**
+     * 供灯下单
+     * @return mixed
+     */
+    public function buy(GongdengValidator $validate){
+        $params = $validate->check(request()->all(),'buy');
+        if(!is_array($params)){
+            return message($params, false);
+        }
+        return $this->service->buy($this->userId);
+    }
 }

+ 67 - 0
app/Http/Controllers/Api/v1/NotifyController.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\BaseController;
+use App\Services\NotifyService;
+use App\Services\RedisService;
+use App\Services\SiyuanService;
+use App\Services\WechatService;
+
+/**
+ * 回调控制器
+ * @author wesmiler
+ * @since 2020/11/10
+ * Class NotifyController
+ * @package App\Http\Controllers
+ */
+class NotifyController extends BaseController
+{
+    /**
+     * 构造函数
+     * @author wesmiler
+     * @since 2020/11/11
+     * NotifyController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->service = new SiyuanService();
+    }
+
+    /**
+     * 支付回调
+     */
+    public function pay($scene){
+        if(empty($scene)){
+            return message('参数错误回调失败', false);
+        }
+
+        $postStr = file_get_contents('php://input');
+        $postData =$postStr? json_decode($postStr, true) : [];
+        $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));
+        }
+
+        $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);
+        if (WechatService::checkJsapiNotify($postData) === true) {
+            switch($scene){
+                case 'index': // 供灯订单
+                    return NotifyService::make()->notifyGongdeng($postData, $outTradeNo);
+                case 'recharge': // 充值
+
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        return message('回调失败', false);
+    }
+}

+ 52 - 0
app/Http/Validator/GongdengValidator.php

@@ -0,0 +1,52 @@
+<?php
+namespace App\Http\Validator;
+class GongdengValidator extends BaseValidator
+{
+    // 当前模型所有验证规则
+    public static $rules = [
+        'id' => 'required',
+        'fid' => 'required',
+        'mid' => 'required',
+        'payType' => 'required',
+        'price' => 'string|min:1|max:10',
+        'sf_name' => 'required|string|min:2|max:30',
+        'qf_content' => 'string|min:4|max:200',
+    ];
+
+    // 当前模型所有错误提示信息
+    public static $msgs = [
+        'required' => ':attribute不能为空',
+        'string' => ':attribute必须是字符串',
+        'min' => ':attribute长度不能小于:min位',
+        'max' => ':attribute长度不能大于:max位',
+        'exists' => ':attribute不存在',
+        'rule' => ':attribute格式不正确',
+    ];
+
+    // 当前模型所有验证字段
+    public static $fields = [
+        'fid' => '佛像ID',
+        'mid' => '套餐',
+        'price' => '套餐价格',
+        'sf_name' => '收福人芳名',
+        'payType' => '支付类型',
+        'xy_content' => '祈福内容',
+    ];
+
+    // 当前模型所有验证场景
+    public static $scenes = [
+        'info'=> ['id'],
+        'buy'=> ['fid','sf_name','pay_type','qf_content'],
+    ];
+
+    /**
+     * 验证
+     * @param $request
+     * @param string $scene
+     * @return int|mixed
+     */
+    public static function check($request, $scene=''){
+        $validator = new BaseValidator(self::$rules, self::$msgs, self::$fields, self::$scenes);
+        return $validator->checkParams($request, $scene);
+    }
+}

+ 104 - 0
app/Services/GongdengOrderService.php

@@ -11,7 +11,10 @@
 
 namespace App\Services;
 
+use App\Models\GongdengFoxiangModel;
 use App\Models\GongdengOrderModel;
+use App\Models\LampMealsModel;
+use App\Models\MemberModel;
 
 /**
  * 供灯管理-服务类
@@ -45,6 +48,107 @@ class GongdengOrderService extends BaseService
         return parent::getList();
     }
 
+    /**
+     * 供灯下单
+     */
+    public function buy($userId){
+        $params = request()->all();
+        // 验证佛像信息
+        $fid = isset($params['fid'])? $params['fid'] : 0;
+        $foInfo = GongdengFoxiangModel::where(['id'=>$fid, 'status'=> 1,'mark'=> 1])
+            ->select(['id','name'])
+            ->first();
+        if(!$foInfo || $fid<=0){
+            return message('供灯佛像信息不存在', false);
+        }
+
+        $payType = isset($params['payType'])? $params['payType'] : 0;
+        if(!in_array($payType, [1])){
+            return message('支付方式暂不支持', false);
+        }
+
+        // 套餐信息
+        $mid = isset($params['mid'])? $params['mid'] : 0;
+        $mealInfo = LampMealsModel::where(['id'=>$mid, 'status'=> 1,'mark'=> 1])
+            ->select(['id','name','price','num'])
+            ->first();
+        if(!$mealInfo){
+            return message('供灯套餐不存在或已下架', false);
+        }
+
+        // 验证用户是否已授权
+        $memberInfo = MemberModel::where(['id'=> $userId, 'mark'=> 1, 'status'=> 1])
+            ->select('id','openid','nickname')
+            ->first();
+        $openid = isset($memberInfo['openid'])? trim($memberInfo['openid']) : '';
+        if(!$memberInfo){
+            return message('账号已被冻结,请联系客服', false);
+        }
+
+        if(empty($openid)){
+            return message('账号获取授权参数失败,请退出重试', false);
+        }
+
+        // 验证是否供灯过
+        $buyType = 1;
+         $gdCheckData = GongdengOrderModel::where(['source_id'=> $fid,'user_id'=> $userId,'status'=>2,'mark'=>1])
+             ->where('expire_time','>=', time())
+             ->select(['id','source_id','user_id','expire_time','params'])
+             ->first();
 
+         // 续费
+        if($gdCheckData){
+            $buyType = 2;
+        }
+
+        // 创建订单
+        $expireTime = ($mealInfo->num*24*3600) + time();
+        $data = [
+            'source_id'=> $fid,
+            'user_id'=> $userId,
+            'pay_type'=> $payType,
+            'buy_type'=> $buyType,
+            'order_sn'=> get_order_num('G'),
+            'num'=> 1,
+            'price'=> $mealInfo->price,
+            'total'=> $mealInfo->price,
+            'sf_name'=> isset($params['sf_name'])? trim($params['sf_name']) : '',
+            'qf_content'=> isset($params['qf_content'])? trim($params['qf_content']) : '',
+            'is_hide'=> isset($params['is_hide'])? intval($params['is_hide']) : 0,
+            'expire_time'=> $expireTime,
+            'create_time'=> time(),
+            'status'=> 1,
+        ];
+
+        // 订单
+        if(!$oid = GongdengOrderModel::insertGetId($data)){
+            return message('供灯订单创建失败', false);
+        }
+
+
+        // 支付参数
+        switch($payType){
+            case 1: // 微信支付
+                $order = [
+                    'openid'=> $openid,
+                    'orderNo'=> $data['order_sn'],
+                    'amount'=> $data['total'],
+                    'body'=> '供灯订单支付',
+                ];
+
+                $jsapiParams = WechatService::jsapiUnifiedorder($order);
+                $code = isset($jsapiParams['code'])? $jsapiParams['code'] : '';
+                var_dump($jsapiParams);
+                if($code == 'error' || empty($jsapiParams)){
+                    return message('支付处理失败', false);
+                }
+                return message('订单创建成功', true, $jsapiParams);
+                break;
+            default:
+                break;
+        }
+
+        return message('支付处理失败', false);
+    }
 
 }

+ 103 - 0
app/Services/NotifyService.php

@@ -0,0 +1,103 @@
+<?php
+// +----------------------------------------------------------------------
+// | Laravel框架 [ Laravel ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 Laravel研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: wesmiler <12345678@qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Services;
+
+use App\Models\GongdengOrderModel;
+use App\Models\SignsModel;
+
+/**
+ * 支付回调管理-服务类
+ * @author wesmiler
+ * @since 2020/11/11
+ * Class NotifyService
+ * @package App\Services
+ */
+class NotifyService extends BaseService
+{
+
+    protected static $instance = null;
+    /**
+     * 构造函数
+     * @author wesmiler
+     * @since 2020/11/11
+     * NotifyService constructor.
+     */
+    public function __construct()
+    {
+        $this->model = new GongdengOrderModel();
+    }
+
+    /**
+     * 静态入口
+     * @return NotifyService|null
+     */
+    public static function make(){
+        if(!self::$instance){
+            self::$instance = new NotifyService();
+        }
+        return self::$instance;
+    }
+
+    /**
+     * 供灯订单回调处理
+     * @param $notifyData
+     * @param $outTradeNo
+     * @return false
+     */
+    public function notifyGongdeng($notifyData, $outTradeNo){
+
+        // 验证订单是否存在
+        $orderInfo = $this->model::where(['order_sn'=> $outTradeNo])
+            ->select(['id','source_id','user_id','num','total','status'])
+            ->first();
+
+        // 验证参数
+        $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : 0;
+        if (empty($orderInfo)) {
+            NotifyService::rebackOk();
+            return false;
+        }
+
+        // 验证订单状态是否可处理
+        if ($orderStatus != 1) {
+            NotifyService::rebackOk();
+            return false;
+        }
+
+        // 验证订单金额是否正确
+        $payDebug = config('weixin.payDebug');
+        $payMoney = isset($postData['total_fee']) ? moneyFormat($postData['total_fee']) : 0;
+        $orderMoney = isset($orderInfo['money']) ? moneyFormat($orderInfo['money']) : 0.00;
+        $credit = isset($orderInfo['credit']) ? moneyFormat($orderInfo['credit']) : 0.00;
+        $orderAmount = moneyFormat($orderMoney + $credit);
+        if (!$payDebug && intval($orderAmount * 100) != intval($payMoney)) {
+            return false;
+        }
+
+        // 更新订单数据
+
+        // 处理支付明细
+
+        // 开灯处理
+
+        // 消息处理
+
+    }
+
+    /**
+     * 返回成功
+     */
+    public static function rebackOk(){
+        echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
+        exit;
+    }
+}

+ 1 - 1
app/Services/SnapshotService.php

@@ -51,7 +51,7 @@ class SnapshotService extends BaseService
             throw new \Exception('缺少参数配置');
         }
 
-        var_dump($config);
+
         $this->uuid = $config['snapshot_uuid']['value']? $config['snapshot_uuid']['value'] : '';
         $this->appKey = $config['snapshot_appkey']['value']? $config['snapshot_appkey']['value'] : $this->appKey;
         $this->appSecret = $config['snapshot_appsecret']['value']? $config['snapshot_appsecret']['value'] : $this->appSecret;

+ 13 - 12
app/Services/WechatService.php

@@ -174,8 +174,8 @@ class WechatService extends BaseService
         $config = $configService->getConfigByGroup(7);
         $config = $config ? $config : $defConfig;
         $config['notify'] = isset($defConfig['notify']) ? $defConfig['notify'] : [];
-        if ($key) {
-            return isset($config[$key]) ? $config[$key]['value'] : '';
+        if ($key && $key != 'notify') {
+            return isset($config[$key]['value']) ? $config[$key]['value'] : '';
         } else {
             return $config ? $config : [];
         }
@@ -434,7 +434,7 @@ class WechatService extends BaseService
         $appId = WechatService::getConfigs('wx_appid');
         $mchId = WechatService::getConfigs('wx_mch_id');
         $notifyUrls = WechatService::getConfigs('notify');
-        $notifyUrl = isset($notifyUrls[$scene]) ? url()->formatRoot('//').$notifyUrls[$scene] : url()->formatRoot('//').'/api/notify/pay/index';
+        $notifyUrl = isset($notifyUrls[$scene]) ? url()->formatRoot('http://').$notifyUrls[$scene] : url()->formatRoot('http://').'/api/notify/pay/index';
         $openid = isset($order['openid']) ? trim($order['openid']) : '';
         $orderNo = isset($order['orderNo']) ? trim($order['orderNo']) : '';
         $totalFee = isset($order['amount']) ? moneyFormat($order['amount']) : 0.00;
@@ -462,18 +462,18 @@ class WechatService extends BaseService
             'trade_type' => 'JSAPI',
         );
 
-        RedisService::set('orders:'.$scene.':'.$openid.':unified', $unified, 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unified', $unified, 600);
         $unified['sign'] = WechatService::getPaySign($unified);
-        RedisService::set('orders:'.$scene.':'.$openid.':unifiedSign', $unified, 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unifiedSign', $unified, 600);
         $url = !empty(self::$apiUrl['unifiedorder']) ? trim(self::$apiUrl['unifiedorder']) : 'https://api.mch.weixin.qq.com/pay/unifiedorder';
         $data = WechatService::arrayToXml($unified);
-        RedisService::set('orders:'.$scene.':'.$openid.':unifiedXml', ['data'=> $unified,'result'=> $data], 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unifiedXml', ['data'=> $unified,'result'=> $data], 600);
         $responseXml = WechatService::curlPost($url, $data);
         //禁止引用外部xml实体
         libxml_disable_entity_loader(true);
         $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
         $unifiedOrder = (array)$unifiedOrder;
-        RedisService::set('orders:'.$scene.':'.$openid.':unifiedResult', ['data'=> $unifiedOrder,'result'=> $data], 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unifiedResult', ['data'=> $unifiedOrder,'result'=> $data], 600);
         if ($unifiedOrder === false) {
             return ['code' => 'exception', 'message' => 'parase xml error'];
         }
@@ -527,19 +527,19 @@ class WechatService extends BaseService
             $unified['re_user_name'] = isset($order['real_name']) ? trim($order['real_name']) : '';
         }
 
-        RedisService::set('orders:'.$scene.':'.$openid.':unified', $unified, 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unified', $unified, 600);
         $unified['sign'] = WechatService::getPaySign($unified);
-        RedisService::set('orders:'.$scene.':'.$openid.':unifiedSign', $unified, 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unifiedSign', $unified, 600);
         $url = !empty(self::$apiUrl['transfers']) ? trim(self::$apiUrl['transfers']) : 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
         $data = WechatService::arrayToXml($unified);
-        RedisService::set('orders:'.$scene.':'.$openid.':unifiedXml', ['data'=> $unified,'result'=> $data], 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unifiedXml', ['data'=> $unified,'result'=> $data], 600);
         $responseXml = WechatService::curlPost($url, $data, [], self::$certPaths);
 
         //禁止引用外部xml实体
         libxml_disable_entity_loader(true);
         $result = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
         $result = (array)$result;
-        RedisService::set('orders:'.$scene.':'.$openid.':unifiedResult', ['data'=> $result,'result'=> $data], 600);
+        RedisService::set('caches:orders:'.$scene.':'.$openid.':unifiedResult', ['data'=> $result,'result'=> $data], 600);
         if ($result === false) {
             return ['code' => 'exception', 'message' => 'parase xml error'];
         }
@@ -718,9 +718,10 @@ class WechatService extends BaseService
         $sign = WechatService::getPaySign($notifyData);
         if ($nofitySign == $sign) {
             echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
+            return true;
         }
 
-        return true;
+        return false;
     }
 
     /**

+ 1 - 1
config/weixin.php

@@ -15,6 +15,6 @@ return [
     'notify' => [
         'jsapiPay' => '/api/notify/pay/index',   // 订单支付回调地址
         'recharge' => '/api/notify/pay/recharge',   // 充值订单支付回调地址
-        'refund' => '/api/notify/refundNotify',   // 订单退款回调地址
+        'refund' => '/api/notify/refund/index',   // 订单退款回调地址
     ],
 ];

+ 2 - 0
routes/api.php

@@ -28,6 +28,8 @@ Route::post('/auth/url', [\App\Http\Controllers\Api\AuthController::class, 'auth
 Route::post('/auth/weixin', [\App\Http\Controllers\Api\AuthController::class, 'check']);
 
 // 支付回调
+Route::any('/notify/pay/{scene}', [\App\Http\Controllers\Api\v1\NotifyController::class, 'pay']);
+Route::any('/notify/refund/{scene}', [\App\Http\Controllers\Api\v1\NotifyController::class, 'check']);
 
 // 用户
 Route::post('/member/info', [\App\Http\Controllers\Api\v1\MemberController::class, 'info']);