2 Commits 996b4e47bf ... c98a13f119

Author SHA1 Message Date
  xiansin c98a13f119 feat: 优化小程序绑定上级,分享没有记录BUG 2 years ago
  xiansin d91e27eabb feat: 快手结算 2 years ago

+ 18 - 1
mini/App.vue

xqd xqd
@@ -1,5 +1,5 @@
 <script>
-
+import Cache from './utils/cache'
 export default {
   globalData: {
     isLogin: false
@@ -9,9 +9,26 @@ export default {
     console.log('App Launch')
     const path = options.path ? '/' + options.path : '/pages/index/index'
     const query = options.query
+    // 直接传递user_id
+    if (typeof query.user_id !== 'undefined' && query.user_id) {
+      Cache.set('parent_id', query.user_id)
+    }
+    // 微信小程序 对应的二维码是 scene_code
+    if (typeof query.scene_code !== 'undefined' && query.scene_code) {
+      Cache.set('parent_id', query.scene_code)
+    }
     if (this.$api.user.isLogin()) {
       await this.$api.user.info().then(res => {
         this.$store.dispatch('user/info', res.data)
+        // 绑定上级
+        const parentId = Cache.get('parent_id')
+        if (parentId && !res.data.info.parent_id) {
+          this.$api.user.bind(parentId).then(res => {
+            console.log('-->bind parent success')
+            this.$store.dispatch('user/info', res.data)
+            Cache.remove('parent_id')
+          })
+        }
       })
     } else {
       uni.reLaunch({

+ 2 - 1
mini/api/episode.js

xqd xqd
@@ -45,7 +45,7 @@ export function list(params) {
 
 export function shared(id) {
   return request.post(
-    `episode/shared/${id}`
+    `episode/${id}/shared`
   )
 }
 
@@ -77,6 +77,7 @@ export default {
   detail,
   trace,
   list,
+  shared,
   search,
   vipFree,
   listBuyNum

+ 1 - 0
mini/api/user/index.js

xqd
@@ -41,6 +41,7 @@ export async function login() {
           { code: loginRes.code, anonymousCode: loginRes.anonymousCode }
         ).then(res => {
           Cache.set('isLogin', 0)
+          const parentId = Cache.get('parent_id')
           resolve(res)
         }).catch(err => {
           Cache.set('isLogin', 0)

+ 1 - 1
mini/components/Recharge/index.vue

xqd
@@ -148,7 +148,7 @@ export default {
     },
     handleRecharge() {
       // IOS 不允许购买
-      // #ifdef MP-TOUTIAO | MP-WEIXIN
+      // #ifdef MP-TOUTIAO
       if (!this.$util.checkOS()) return
       // #endif
       const item = this.combos[this.rechargeActive]

+ 2 - 2
mini/manifest.json

xqd
@@ -76,8 +76,8 @@
     "mp-toutiao" : {
         "usingComponents" : true,
         "appid" : "tta9e8df5536d6b48b01",
-        "setting": {
-          "urlCheck": false
+        "setting" : {
+            "urlCheck" : false
         }
     },
     "uniStatistics" : {

+ 8 - 8
mini/pages/episode/play.vue

xqd xqd
@@ -339,8 +339,9 @@ export default {
       })
     },
     // 分享
-    handleShared(id, list_id) {
-      this.$api.episode.shared(id, list_id).then(res => {
+    handleShared(id) {
+      console.log('-->handleShared success')
+      this.$api.episode.shared(id).then(res => {
         this.episode.share_count += 1
       })
     },
@@ -418,17 +419,16 @@ export default {
     }
     let options = {
       title: '',
-      path: `/pages/episode/play?id=${this.id}`
+      path: `/pages/episode/play?id=${this.id}&user_id=${this.userInfo.user_id}`
     }
     if (this.episode) {
+      // 没有success 回调 只要点击分享了就默认成功
+      this.handleShared(this.id)
       options = {
         title: this.episode.name,
-        path: `/pages/episode/play?id=${this.id}`,
+        path: `/pages/episode/play?id=${this.id}&user_id=${this.userInfo.user_id}`,
         imageUrl: this.episode.cover_img,
-        desc: this.episode.name,
-        success: res => {
-          this.handleShared(this.id, this.currentEpisode.id)
-        }
+        desc: this.episode.name
       }
     }
     return options

+ 0 - 5
mini/pages/index/index.vue

xqd
@@ -80,11 +80,6 @@ export default {
   onLoad(options) {
     console.log('-->index data', options)
     this.isLogin && this.getHomeColumn()
-    this.scene_code = typeof options.user_id !== 'undefined' ? options.scene : ''
-    this.parent_id = typeof options.user_id !== 'undefined' ? options.user_id : 0
-    if ((this.parent_id || this.scene_code) && !this.userInfo.parent_id) {
-      this.isLogin && this.bindParent()
-    }
   },
   methods: {
     handleSearch() {

+ 11 - 0
mini/pages/login.vue

xqd xqd
@@ -10,6 +10,8 @@
 </template>
 
 <script>
+import Cache from '../utils/cache'
+
 export default {
   components: {},
 
@@ -28,6 +30,15 @@ export default {
         const { token, user_info } = res.data
         await this.$store.dispatch('user/token', token)
         await this.$store.dispatch('user/info', user_info)
+        // 绑定上级
+        const parentId = Cache.get('parent_id')
+        if (parentId && !user_info.info.parent_id) {
+          this.$api.user.bind(parentId).then(res => {
+            console.log('-->bind parent success')
+            this.$store.dispatch('user/info', res.data)
+            Cache.remove('parent_id')
+          })
+        }
         this.relaunch()
       }).catch(async() => {
         await this.$store.dispatch('user/clear')

+ 1 - 1
mini/pages/member/index.vue

xqd
@@ -73,7 +73,7 @@ export default {
       // this.modal.show = true
     },
     handleBuy() {
-      // #ifdef MP-TOUTIAO | MP-WEIXIN
+      // #ifdef MP-TOUTIAO
       if (!this.$util.checkOS()) return
       // #endif
       const item = this.settings[this.activeIndex]

+ 54 - 0
server/app/Helper/Kuaishou.php

xqd
@@ -71,6 +71,60 @@ class Kuaishou extends BaseUniPlatform
         ];
     }
 
+    public function settle($orderNo, $amount)
+    {
+        $url = $this->API::SETTLE.'?'.http_build_query([
+                'app_id' => $this->appId,
+                'access_token' =>  $this->accessToken,
+            ]);
+        $data = [
+            'app_id'        => $this->appId,
+            'out_order_no'  => $orderNo,
+            'out_settle_no' => $orderNo,
+            'reason'        => '主动结算',
+            'notify_url'    => env('APP_URL') . '/api/pay/kuaishou/settle',
+            'settle_amount' => $amount
+        ];
+        $data['sign'] = $this->getSign($data);
+
+        return $this->post(
+            $url,
+            $data,
+            'json'
+        );
+    }
+
+    public function pushOrder($openid, $orderId): array
+    {
+        $data = [
+            'app_id'               => $this->appId,
+            'out_order_no'         => $orderId,
+            'out_biz_order_no'     => $orderId,
+            'open_id'              => $openid,
+            'order_create_time'    => (int)Carbon::now()->subDays(7)->getPreciseTimestamp(3),
+            'order_status'         => 2, // 支付成功
+            'order_path'           => 'pages/my/consume',
+            'product_cover_img_id' => '5acfa29b90c8234ff41ede600cad6a9b715f38871eaf5973',
+        ];
+        $url = $this->API::ORDER_PUSH.'?'.http_build_query([
+                'app_id' => $this->appId,
+                'access_token' =>  $this->accessToken,
+            ]);
+        return $this->post($url, $data,'json');
+    }
+
+    public function upload()
+    {
+        $url = 'https://open.kuaishou.com/openapi/mp/developer/file/img/uploadWithUrl'.'?'.http_build_query([
+                'app_id' => $this->appId,
+                'access_token' =>  $this->accessToken,
+                'url' => 'http://fourtiao.oss-cn-beijing.aliyuncs.com/zhangsiye/images/664b34c5afb8cb56d4a3cec398e64948.png'
+            ]);
+        return $this->post(
+            $url,
+        );
+    }
+
 
     /**
      * @param array  $data

+ 12 - 0
server/app/Helper/UniPlatform/Kuaishou/KuaishouAPI.php

xqd
@@ -31,4 +31,16 @@ final class KuaishouAPI extends BaseAPI
      * @url https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/server/qr-code/create-qr-code
      */
     const CREATE_QRCODE =  '';
+
+    /**
+     * 同步订单
+     * @url https://mp.kuaishou.com/docs/develop/server/order/push.html
+     */
+    const ORDER_PUSH = PAY_URL.'/order/v1/report';
+
+    /**
+     * 结算
+     * @url https://mp.kuaishou.com/docs/develop/server/epay/interfaceDefinition.html#_3%E3%80%81%E6%94%AF%E4%BB%98%E7%BB%93%E7%AE%97
+     */
+    const SETTLE = PAY_URL.'/epay/settle';
 }

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

xqd xqd xqd
@@ -65,8 +65,9 @@ class PayNoticeController extends Controller
 
     public function kuaishou(): JsonResponse
     {
-        $app = new KuaishouPayment($this->getUniFactory(2));
-        return $app->payNotify(function ($data, $fail) {
+        $factory = $this->getUniFactory(2);
+        $app = new KuaishouPayment($factory);
+        return $app->payNotify(function ($data, $fail) use($factory) {
             //处理支付订单
             try {
                 \DB::beginTransaction();
@@ -89,9 +90,15 @@ class PayNoticeController extends Controller
                 $pay->save();
                 // 处理
                 if ($pay->source == Pay::SOURCE_RECHARGE) {
-                    $this->recharge($payId);
+                    $goods = $this->recharge($payId);
                 } else if ($pay->source == Pay::SOURCE_BUY_VIP) {
-                    $this->buyVip($payId);
+                    $goods = $this->buyVip($payId);
+                }
+
+                if(isset($goods)){
+                    /* @var Pay $payInfo*/
+                    $payInfo = Pay::with(['user'])->where('pay_id', $payId)->first();
+                    $factory->pushOrder($payInfo->user->open_id, $payId);
                 }
 
                 \DB::commit();
@@ -106,6 +113,14 @@ class PayNoticeController extends Controller
         });
     }
 
+    public function kuaishouSettle()
+    {
+        $app = new KuaishouPayment($this->getUniFactory(2));
+        return $app->payNotify(function ($data, $fail) {
+            return true;
+        });
+    }
+
     /**
      * @return Response
      * @throws \EasyWeChat\Kernel\Exceptions\Exception

+ 76 - 0
server/app/Jobs/KuaishouSettlementJob.php

xqd
@@ -0,0 +1,76 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Helper\ByteDance;
+use App\Helper\Kuaishou;
+use App\Helper\UniPlatform\Bytedance\ByteDanceAPI;
+use App\Helper\UniPlatform\Kuaishou\KuaishouAPI;
+use App\Models\Pay;
+use App\Models\PayConfig;
+use Carbon\Carbon;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Psy\Util\Json;
+
+class KuaishouSettlementJob implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        //
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $app = $this->getKuishouFactory();
+
+        $orders = Pay::with(['user.info'])->whereHas('user.info', function ($query){
+            $query->where('platform', 2);
+        })->where('status', 1)
+            ->where('created_at', '<=',Carbon::now()->subDays(7)->toDateString().' 00:00:00')
+            ->where('is_settle', 0)
+            ->get()
+            ->chunk(30);
+        foreach ($orders as $arr){
+            /* @var Pay $order*/
+            foreach ($arr as $order){
+                try {
+                    $res = $app->settle($order->pay_id, $order->order_fee * 100);
+                    $order->is_settle = 1;
+                    $order->settle_no = $res['settle_no'];
+                    $order->save();
+                    \Log::info("快手结算--> 支付订单号:{$order->pay_id}\t结算单号:{$res['settle_no']}");
+                }catch (\Exception $e) {
+                    \Log::info("快手结算错误--> 支付订单号:{$order->pay_id}\n错误信息:{$e->getMessage()}");
+                }
+            }
+            // 30QPS
+            sleep(1);
+        }
+
+    }
+
+    protected function getKuishouFactory(): Kuaishou
+    {
+        $setting = PayConfig::first();
+        return (new Kuaishou(app(KuaishouAPI::class)))->factory([
+            'app_id'     => $setting->kuaishou_app_id,
+            'app_secret' => $setting->kuaishou_app_secret,
+        ]);
+    }
+}

+ 1 - 0
server/routes/api.php

xqd
@@ -192,6 +192,7 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\V1'], function ($api)
             $api->get('vip/free', 'EpisodeController@vipFree'); // banner
             $api->get('{id}/detail', 'EpisodeController@detail'); // 详情
             $api->get('/list/{listId}/buyNum', 'EpisodeController@listBuyNum'); // 详情
+            $api->post('{id}/shared', 'EpisodeController@shared'); // 分享
         });
 
     });