xiansin пре 2 година
родитељ
комит
1587bd6f0a

+ 49 - 19
server/app/Helper/ByteDance.php

xqd xqd
@@ -3,6 +3,8 @@
 namespace App\Helper;
 
 use App\Helper\Bytedance\ByteDanceAPI;
+use App\Models\Pay;
+use Carbon\Carbon;
 use GuzzleHttp\Client;
 use GuzzleHttp\Exception\GuzzleException;
 
@@ -219,52 +221,80 @@ class ByteDance
     }
 
     /**
-     * @param array  $body
-     * @param string $secret
+     * @param array  $data
      * @return string
      */
-    public function getNotifySign(array $body, string $secret)
+    public function getNotifySign(array $data)
     {
         $filtered = [];
-        foreach ($body as $key => $value) {
+        foreach ($data as $key => $value) {
             if (in_array($key, ['msg_signature', 'type'])) {
                 continue;
             }
+            $value = trim(strval($value));
+            $len = strlen($value);
+            if ($len > 1 && substr($value, 0, 1) == "\"" && substr($value, $len, $len - 1) == "\"")
+                $value = substr($value, 1, $len - 1);
             $filtered[] =
                 is_string($value)
                     ? trim($value)
                     : $value;
         }
-        $filtered[] = trim($secret);
+        $filtered[] = trim($this->token);
         sort($filtered, SORT_STRING);
-        $filtered = trim(implode('', $filtered));
-
-        return sha1($filtered);
+        return sha1(trim(implode('', $filtered)));
     }
 
     /**
+     * @param \Closure $closure
      * @return \Illuminate\Http\JsonResponse
+     * @throws \Exception
      */
-    public function notify()
+    public function payNotify(\Closure $closure)
     {
-        $notify = \request()->all();
+        call_user_func($closure, $this->getNoticeData());
 
-        \Log::info('抖音支付回调==>'.json_encode($notify,JSON_UNESCAPED_SLASHES));
-        if ($notify['msg_signature'] !== $this->getNotifySign($notify, $this->appId)) {
+        return response()->json($data);
+
+        if ($notify['msg_signature'] !== $this->getNotifySign($notify)) {
             \Log::error('回调验证错误');
+            $data = [
+                'err_no' => 1,
+                'err_tips' => 'fail'
+            ];
         } else {
-            //获取订单信息
             $order = json_decode($notify['msg'], true);
             //处理订单
-            $data = ['order_sn' => $order['cp_orderno']];
+            $payId = $order['cp_orderno'];
+
+            $pay = Pay::find($payId);
+            $pay->pay_type = $order['way'];
+            $pay->serial_number = $order['channel_no'];
+            $pay->status = $order['status'] == 'SUCCESS';
+            $pay->pay_dt = Carbon::now()->toDateString();
+            $pay->save();
 
 
-            \Log::info('抖音担保支付效验成功');
+            $data = [
+                'err_no'    => 0,
+                'err_tips'  => 'success'
+            ];
         }
-        $data = [
-            'err_no' => 0,
-            'err_tips' => 'success'
-        ];
         return response()->json($data);
     }
+
+    private function getNoticeData()
+    {
+        $notify = \request()->all();
+        $notify = '{"msg":"{\"appid\":\"tt5b312d8cc40f46b701\",\"cp_orderno\":\"10022082800824490007\",\"cp_extra\":\"\",\"way\":\"2\",\"channel_no\":\"2022082822001477591433078541\",\"channel_gateway_no\":\"\",\"payment_order_no\":\"PCP2022082822540531221069106962\",\"out_channel_order_no\":\"2022082822001477591433078541\",\"total_amount\":1,\"status\":\"SUCCESS\",\"seller_uid\":\"71227862181355706950\",\"extra\":\"\",\"item_id\":\"\",\"paid_at\":1661698458,\"message\":\"\",\"order_id\":\"7136939355201063205\",\"trade_item_list\":null,\"ec_pay_trade_no\":\"NEP2022082822540409483061846962\"}","msg_signature":"804a60e48936b14a739230cef21fe6204427732e","nonce":"78","timestamp":"1661698459","type":"payment"}';
+        //获取订单信息
+        $notify = json_decode($notify,true);
+        \Log::info('抖音支付回调==>'.json_encode($notify,JSON_UNESCAPED_SLASHES));
+
+        if($notify['msg_signature'] !== $this->getNotifySign($notify)){
+            throw new \Exception('签名验证错误');
+        }
+
+        return json_decode($notify['msg'], true);
+    }
 }

+ 81 - 0
server/app/Helper/Bytedance/Payment.php

xqd
@@ -0,0 +1,81 @@
+<?php
+
+namespace App\Helper\Bytedance;
+
+use App\Helper\ByteDance;
+use App\Models\Pay;
+use Carbon\Carbon;
+
+/**
+ * Class Payment
+ *
+ * @package App\Helper\Bytedance
+ * @property-read ByteDance $app
+ */
+class Payment
+{
+
+    private $app;
+
+    private $fail = null;
+
+
+    public function __construct(ByteDance $app)
+    {
+        $this->app = $app;
+    }
+
+    /**
+     * 支付通知
+     * @param \Closure $closure
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function payNotify(\Closure $closure)
+    {
+        try {
+            call_user_func($closure, $this->getNoticeData() ,[$this, 'fail']);
+        }catch (\Exception $e){
+            $this->fail($e->getMessage());
+        }
+
+        return $this->toResponse();
+    }
+
+    public function fail($msg)
+    {
+        $this->fail = $msg;
+    }
+
+    /**
+     * 获取支付通知数据
+     * @return mixed
+     * @throws \Exception
+     */
+    private function getNoticeData()
+    {
+        $notify = \request()->all();
+        $notify = '{"msg":"{\"appid\":\"tt5b312d8cc40f46b701\",\"cp_orderno\":\"10022082800824490007\",\"cp_extra\":\"\",\"way\":\"2\",\"channel_no\":\"2022082822001477591433078541\",\"channel_gateway_no\":\"\",\"payment_order_no\":\"PCP2022082822540531221069106962\",\"out_channel_order_no\":\"2022082822001477591433078541\",\"total_amount\":1,\"status\":\"SUCCESS\",\"seller_uid\":\"71227862181355706950\",\"extra\":\"\",\"item_id\":\"\",\"paid_at\":1661698458,\"message\":\"\",\"order_id\":\"7136939355201063205\",\"trade_item_list\":null,\"ec_pay_trade_no\":\"NEP2022082822540409483061846962\"}","msg_signature":"804a60e48936b14a739230cef21fe6204427732e","nonce":"78","timestamp":"1661698459","type":"payment"}';
+        //获取订单信息
+        $notify = json_decode($notify,true);
+        \Log::info('抖音支付回调==>'.json_encode($notify,JSON_UNESCAPED_SLASHES));
+
+        if($notify['msg_signature'] !== $this->app->getNotifySign($notify)){
+            throw new \Exception('签名验证错误');
+        }
+
+        return json_decode($notify['msg'], true);
+    }
+
+    /**
+     * 返回数据
+     * @return \Illuminate\Http\JsonResponse
+     */
+    private function toResponse()
+    {
+        $data = [
+            'err_no'    => is_null($this->fail) ? 0  : 1,
+            'err_tips'  => is_null($this->fail) ? 'success' : $this->fail
+        ];
+        return response()->json($data);
+    }
+}

+ 87 - 4
server/app/Http/Controllers/V1/PayNoticeController.php

xqd
@@ -3,18 +3,101 @@
 namespace App\Http\Controllers\V1;
 
 
+use App\Helper\Bytedance\Payment;
+use App\Models\Pay;
+use App\Models\UserConsumeRecord;
+use App\Models\UserInfo;
+use App\Models\UserRechargeRecord;
+use App\Models\UserVipRecord;
+use Carbon\Carbon;
+
 class PayNoticeController extends Controller
 {
     public function bytedance()
     {
-        try {
+        $app = new Payment($this->getByteDanceFactory());
+        return $app->payNotify(function ($data, $fail) {
+            //处理支付订单
+            try {
+                \DB::beginTransaction();
+                $payId = $data['cp_orderno'];
+                $pay = Pay::find($payId);
+                if (!$pay) { // 如果订单不存在
+                    return true;
+                }
+                $pay->pay_type = $data['way'];
+                $pay->serial_number = $data['channel_no'];
+                $pay->status = $data['status'] == 'SUCCESS';
+                $pay->pay_dt = Carbon::now()->toDateString();
+                $pay->save();
+                // 处理
+                if ($pay->source == Pay::SOURCE_RECHARGE) {
+                    $this->recharge($payId);
+                } else if ($pay->source == Pay::SOURCE_BUY_VIP) {
+                    $this->buyVip($payId);
+                }
+
+
+                \DB::commit();
+            } catch (\Exception $e) {
+                \DB::rollBack();
+                return $fail('通信失败,请稍后再通知我');
+            }
+            return true;
+        });
+    }
+
+    private function recharge($payId)
+    {
+        /* @var UserRechargeRecord $record */
+        $record = UserRechargeRecord::where('pay_id', $payId)->first();
+        if (!$record) {
+            return true;
+        }
+        $user = UserInfo::find($record->user_id);
+
+        // 记录日志
+        $gold = $record->gold + $record->gift;
+        app(UserConsumeRecord::class)->record(
+            $user->user_id,
+            UserConsumeRecord::TYPE_RECHARGE,
+            $gold,
+            "购买金币,combo_id:{$record->combo_id}"
+        );
 
-            $app = $this->getByteDanceFactory();
-            $app->notify();
 
-        }catch (\Exception $e){
+        // 发放奖励
+        $user->integral = $user->integral + $gold;
+        $user->total_integral = $user->total_integral + $gold;
+        $user->save();
 
+
+        $record->status = 1;
+        $record->save();
+
+    }
+
+    private function buyVip($payId)
+    {
+        /* @var UserVipRecord $record */
+        $record = UserVipRecord::where('pay_id', $payId)->first();
+        if (!$record) {
+            return true;
+        }
+        $user = UserInfo::find($record->user_id);
+        if (empty($user->is_vip)) {
+            $user->is_vip = 1;
+            $user->start_at = Carbon::now()->toDateString();
+            $user->end_at = Carbon::now()->addDays($record->valid_day)->toDateString();
+        } else {
+            list($year, $month, $day) = explode('-', $user->end_at);
+            $user->end_at = Carbon::createFromDate($year, $month, $day)->addDays($record->valid_day)->toDateString();
         }
+        $user->save();
+
+        $record->status = 1;
+        $record->save();
+
     }
 }
 

+ 6 - 9
server/app/Http/Controllers/V1/User/EpisodeController.php

xqd
@@ -53,15 +53,12 @@ class EpisodeController extends Controller
             $record->save();
 
             // 记录日志
-            $record = new UserConsumeRecord();
-            $record->user_id = \user()->id;
-            $record->type = 2; // 消费
-            $record->before = $user->integral;
-            $record->change = -$list->sale_price;
-            $record->current = $user->integral - $list->sale_price;
-            $record->remark = "购买短剧 {$episode->name} 第{$list->sort}集";
-            $record->save();
-
+            app(UserConsumeRecord::class)->record(
+                \user()->id,
+                UserConsumeRecord::TYPE_CONSUME,
+                -$list->sale_price,
+                "购买短剧 {$episode->name} 第{$list->sort}集"
+            );
             // 扣除金币
             $user->integral = $user->integral - $list->sale_price;
             $user->save();

+ 1 - 1
server/app/Http/Controllers/V1/User/RechargeController.php

xqd
@@ -56,7 +56,7 @@ class RechargeController extends Controller
                     'pay_id' => $pay->pay_id,
                 ];
             }else{
-                $res = app(Pay::class)->create($app, $combo->price);
+                $res = app(Pay::class)->create($app, $combo->price, Pay::SOURCE_RECHARGE);
 
                 $recharge = new UserRechargeRecord();
                 $recharge->user_id = \user()->id;

+ 6 - 8
server/app/Http/Controllers/V1/User/SignController.php

xqd
@@ -45,14 +45,12 @@ class SignController extends Controller
             $user = UserInfo::find(\user()->id);
 
             // 记录日志
-            $record = new UserConsumeRecord();
-            $record->user_id = \user()->id;
-            $record->type = 3; // 签到
-            $record->before = $user->integral;
-            $record->change = $award;
-            $record->current = $user->integral + $award;
-            $record->remark = "{$today}签到奖励";
-            $record->save();
+            app(UserConsumeRecord::class)->record(
+                \user()->id,
+                UserConsumeRecord::TYPE_SIGN,
+                $award,
+                "{$today}签到奖励"
+            );
 
             // 发放奖励
             $user->integral = $user->integral + $award;

+ 1 - 1
server/app/Http/Controllers/V1/User/VipController.php

xqd
@@ -48,7 +48,7 @@ class VipController extends Controller
                     'pay_id' => $pay->pay_id,
                 ];
             }else{
-                $res = app(Pay::class)->create($app, $combo->price);
+                $res = app(Pay::class)->create($app, $combo->price,Pay::SOURCE_BUY_VIP);
 
                 $recharge = new UserVipRecord();
                 $recharge->user_id = \user()->id;

+ 8 - 2
server/app/Models/Pay.php

xqd xqd xqd
@@ -52,6 +52,11 @@ use Illuminate\Database\Eloquent\Model;
 class Pay extends Model
 {
     use HasFactory;
+
+    const SOURCE_RECHARGE = 1;
+
+    const SOURCE_BUY_VIP = 2;
+
     protected $table = 'pay';
 
     protected $primaryKey = 'pay_id';
@@ -63,10 +68,11 @@ class Pay extends Model
     /**
      * @param ByteDance $byteDance
      * @param           $price
+     * @param int       $source
      * @return array|mixed
      * @throws \Exception
      */
-    public function create(ByteDance $byteDance, $price)
+    public function create(ByteDance $byteDance, float $price, int $source)
     {
         $payId = SerialNumber::createOrderId(\user()->id);
         // 字节跳动下单
@@ -77,7 +83,7 @@ class Pay extends Model
         $pay->pay_id = $payId;
         $pay->user_id = \user()->id;
         $pay->order_fee = $price;
-        $pay->source = 1;
+        $pay->source = $source;
         $pay->prepay_id = $res['order_id'];
         $pay->token = $res['order_token'];
         $pay->save();

+ 17 - 0
server/app/Models/UserConsumeRecord.php

xqd xqd
@@ -42,6 +42,10 @@ class UserConsumeRecord extends Model
 {
     use HasFactory, UserScope;
 
+    const TYPE_RECHARGE = 1;
+    const TYPE_CONSUME = 2;
+    const TYPE_SIGN = 3;
+
     protected $casts = [
         'before' => 'integer',
         'change' => 'integer',
@@ -57,4 +61,17 @@ class UserConsumeRecord extends Model
     {
         return $this->belongsTo(User::class,'user_id','id');
     }
+
+    public function record($userId, $type, $change, $remark)
+    {
+        $record = new UserConsumeRecord();
+        $user = UserInfo::find($userId);
+        $record->user_id = $user->user_id;
+        $record->type = $type;
+        $record->before = $user->integral;
+        $record->change = $change;
+        $record->current = $user->integral + $record->change;
+        $record->remark = $remark;
+        $record->save();
+    }
 }

+ 2 - 2
server/app/Models/UserRechargeRecord.php

xqd xqd
@@ -14,7 +14,7 @@ use Illuminate\Database\Eloquent\Model;
  * @property int $user_id user_id
  * @property int $combo_id 套餐ID
  * @property string $price 支付金额 1:1 金币
- * @property string $gift 赠送金币
+ * @property float $gift 赠送金币
  * @property int $pay_id 支付ID
  * @property \Illuminate\Support\Carbon $updated_at 删除时间
  * @property string $deleted_at 删除时间
@@ -34,7 +34,7 @@ use Illuminate\Database\Eloquent\Model;
  * @mixin \Eloquent
  * @property-read \App\Models\RechargeCombo|null $combo
  * @property-read \App\Models\User|null $user
- * @property string $gold 充值奖励金币
+ * @property float $gold 充值奖励金币
  * @property-read \App\Models\Pay|null $pay
  * @method static \Illuminate\Database\Eloquent\Builder|UserRechargeRecord whereGold($value)
  * @property int $status 充值状态

+ 6 - 0
server/config/global.php

xqd
@@ -37,5 +37,11 @@ return [
         5 => ['name' => '第五天', 'award' => 20],
         6 => ['name' => '第六天', 'award' => 30],
         7 => ['name' => '第七天', 'award' => 50],
+    ],
+    'pay_type' => [
+        1 => '微信支付', 2  => '支付宝支付', 10 => '抖音支付'
+    ],
+    'pay_source' => [
+        1 => '微信支付', 2  => '支付宝支付', 10 => '抖音支付'
     ]
 ];