From b4be5a65b4f8e2fb803121fd67ca130439bdbc3e Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Tue, 27 Jun 2023 17:59:35 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E6=94=B6=E8=B4=A7=EF=BC=8C=E5=86=99=E5=85=A5=E8=AE=A1=E6=81=AF?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/dao/store/order/StoreOrderDao.php | 3 ++ app/common/model/store/order/StoreOrder.php | 6 +++ .../model/store/order/StoreOrderInterest.php | 23 +++++++++ .../order/StoreOrderInterestRepository.php | 18 +++++++ .../store/order/StoreOrderRepository.php | 9 +++- .../store/product/ProductRepository.php | 47 +++++++++++++++++++ .../api/store/product/StoreMicro.php | 41 +++------------- app/event.php | 1 + app/listener/OrderTake.php | 36 ++++++++++++++ 9 files changed, 148 insertions(+), 36 deletions(-) create mode 100644 app/common/model/store/order/StoreOrderInterest.php create mode 100644 app/common/repositories/store/order/StoreOrderInterestRepository.php create mode 100644 app/listener/OrderTake.php diff --git a/app/common/dao/store/order/StoreOrderDao.php b/app/common/dao/store/order/StoreOrderDao.php index 8e9cd5fd..31966cbe 100644 --- a/app/common/dao/store/order/StoreOrderDao.php +++ b/app/common/dao/store/order/StoreOrderDao.php @@ -91,6 +91,9 @@ class StoreOrderDao extends BaseDao ->when(isset($where['activity_type']) && $where['activity_type'] != '', function ($query) use ($where) { $query->where('activity_type', $where['activity_type']); }) + ->when(isset($where['product_type']) && $where['product_type'] != '', function ($query) use ($where) { + $query->where('activity_type', $where['product_type']); + }) ->when(isset($where['status']) && $where['status'] !== '', function ($query) use ($where) { switch ($where['status']) { case 0 : diff --git a/app/common/model/store/order/StoreOrder.php b/app/common/model/store/order/StoreOrder.php index 77ab9451..2a145adb 100644 --- a/app/common/model/store/order/StoreOrder.php +++ b/app/common/model/store/order/StoreOrder.php @@ -177,4 +177,10 @@ class StoreOrder extends BaseModel { return StoreRefundOrder::where('order_id',$this->order_id)->where('status',3)->sum('refund_price'); } + + public function interest() + { + return $this->hasOne(StoreOrderInterest::class, 'order_id', 'order_id'); + } + } diff --git a/app/common/model/store/order/StoreOrderInterest.php b/app/common/model/store/order/StoreOrderInterest.php new file mode 100644 index 00000000..64cd7c14 --- /dev/null +++ b/app/common/model/store/order/StoreOrderInterest.php @@ -0,0 +1,23 @@ +insert($data); + } + +} diff --git a/app/common/repositories/store/order/StoreOrderRepository.php b/app/common/repositories/store/order/StoreOrderRepository.php index 97a88513..35490fe1 100644 --- a/app/common/repositories/store/order/StoreOrderRepository.php +++ b/app/common/repositories/store/order/StoreOrderRepository.php @@ -1689,8 +1689,15 @@ class StoreOrderRepository extends BaseRepository $order->presell_price = $order->pay_price; } } + if ($order->pay_type == StoreGroupOrder::PAY_TYPE_CREDIT_BUY && $order->interest) { + $order->interest_start_time = $order->interest->start_time; + $days = ceil((time() - strtotime($order->interest->start_time)) / 86400); + $interestMoney = bcmul($order->interest->total_price, $order->interest->rate, 2); + $order->interest_money = bcmul($days, $interestMoney, 2); + $order->interest_status = $order->interest->status; + } $order->takeOrderCount = count($order['takeOrderList']); - unset($order['takeOrderList']); + unset($order['takeOrderList'], $order->interest); } return compact( 'count','list'); diff --git a/app/common/repositories/store/product/ProductRepository.php b/app/common/repositories/store/product/ProductRepository.php index 77f65452..46cc4586 100644 --- a/app/common/repositories/store/product/ProductRepository.php +++ b/app/common/repositories/store/product/ProductRepository.php @@ -2299,4 +2299,51 @@ class ProductRepository extends BaseRepository return true; } + /** + * 导入商品 + * @param $product_id + * @param $user + * @return bool + * @throws \Exception + */ + public function import($product_id, $user) + { + $mer_id = Db::name('store_service')->where('uid', $user['uid'])->where('status', 1)->value('mer_id'); + if ($mer_id == 0) { + throw new \Exception('商户不存在'); + } + $find = Db::name('store_product')->where('product_id', $product_id)->find(); + if ($find) { + if ($find['product_type'] != 0) { + throw new \Exception('该商品不是普通商品'); + } + $exist = Db::name('store_product')->where('old_product_id', $product_id)->where('mer_id', $mer_id)->find(); + if ($exist) { + throw new \Exception('已经导入过该商品了'); + } + $find['attrValue'] = Db::name('store_product_attr_value')->where('product_id', $find['product_id'])->field('image,price,cost,ot_price,svip_price,stock,bar_code,weight,volume')->select(); + $find['content'] = Db::name('store_product_content')->where('product_id', $find['product_id'])->value('content'); + $find['is_show'] = 0; + $find['mer_id'] = $mer_id; + $find['temp_id'] = ""; + $find['give_coupon_ids'] = []; + $find['params'] = []; + $find['extend'] = []; + $find['param_temp_id'] = []; + $find['mer_labels'] = []; + $find['attr'] = []; + $find['delivery_way'] = [0 => "2"]; + $find["guarantee_template_id"] = ""; + $find['product_type'] = 0; + $find['mer_cate_id'] = [0 => 0]; + $find['is_used'] = 1; + $find['status'] = 1; + $find['mer_status'] = 1; + $find['old_product_id'] = $product_id; + $find['slider_image'] = explode(',', $find['slider_image']); + unset($find['product_id'], $find['create_time']); + } + return $this->create($find, 0); + } + } diff --git a/app/controller/api/store/product/StoreMicro.php b/app/controller/api/store/product/StoreMicro.php index 4e854beb..9b40d72d 100644 --- a/app/controller/api/store/product/StoreMicro.php +++ b/app/controller/api/store/product/StoreMicro.php @@ -50,42 +50,13 @@ class StoreMicro extends BaseController public function ProductImport(){ $product_id = $this->request->param('id', 0); $user = $this->request->userInfo(); - $mer_id =Db::name('store_service')->where('uid',$user['uid'])->where('status',1)->value('mer_id'); - if ($mer_id==0) return app('json')->fail('商户id不能为空'); - $find=Db::name('store_product')->where('product_id',$product_id)->find(); - if($find){ - if($find['product_type']!=0){ - return app('json')->fail('该商品不是普通商品'); - } - $exist = Db::name('store_product')->where('old_product_id', $product_id)->where('mer_id', $mer_id)->find(); - if($exist){ - return app('json')->fail('已经导入过该商品了'); - } - $find['attrValue']=Db::name('store_product_attr_value')->where('product_id',$find['product_id'])->field('image,price,cost,ot_price,svip_price,stock,bar_code,weight,volume')->select(); - $find['content']=Db::name('store_product_content')->where('product_id',$find['product_id'])->value('content'); - $find['is_show']=0; - $find['mer_id']=$mer_id; - $find['temp_id']=""; - $find['give_coupon_ids']=[]; - $find['params']=[]; - $find['extend']=[]; - $find['param_temp_id']=[]; - $find['mer_labels']=[]; - $find['attr']=[]; - $find['delivery_way']=[ 0 => "2"]; - $find["guarantee_template_id"] = ""; - $find['product_type']=0; - $find['mer_cate_id']=[0 => 0]; - $find['is_used']=1; - $find['status']=1; - $find['mer_status']=1; - $find['old_product_id']=$product_id; - $find['slider_image']=explode(',',$find['slider_image']); - unset($find['product_id'],$find['create_time']); + try { + /** @var ProductRepository $productRepository */ + $productRepository = app()->make(ProductRepository::class); + $a = $productRepository->import($product_id, $user); + } catch (\Exception $e) { + return app('json')->fail($e->getMessage()); } - /** @var ProductRepository $make */ - $make = app()->make(ProductRepository::class); - $a=$make->create($find,0); if($a){ return app('json')->success(['data'=>$a,'msg'=>'导入成功']); }else{ diff --git a/app/event.php b/app/event.php index f9f7d132..089e8908 100644 --- a/app/event.php +++ b/app/event.php @@ -67,6 +67,7 @@ return [ 'product.create'=>[\app\listener\ProductCreate::class], 'product.sell'=>[\app\listener\CloudProduct::class], //商品上下架 'refund.after'=>[\app\listener\AfterRefund::class], + 'order.take'=>[\app\listener\OrderTake::class], ], 'subscribe' => [], diff --git a/app/listener/OrderTake.php b/app/listener/OrderTake.php new file mode 100644 index 00000000..859e6c3b --- /dev/null +++ b/app/listener/OrderTake.php @@ -0,0 +1,36 @@ +make(StoreOrderInterestRepository::class); + $merchantId = Merchant::where('uid', $order['uid'])->value('mer_id'); + $data = [ + 'order_id' => $order['order_id'], + 'mer_id' => $merchantId, + 'to_mer_id' => $order['mer_id'], + 'total_price' => $order['total_price'], + 'rate' => $order['merchant']['interest_rate'], + 'start_time' => date('Y-m-d H:i:s', strtotime("+{$order['merchant']['settle_cycle']} days")), + ]; + return $storeOrderInterestRepository->create($data); + } + +} From c67d617fe67984f87270190027f6c00f2e447c7c Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Wed, 28 Jun 2023 15:26:01 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E8=B0=83=E8=AF=95=E4=BF=A1=E7=94=A8?= =?UTF-8?q?=E8=B4=AD=E8=AE=A2=E5=8D=95=E7=BB=93=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/store/order/StoreGroupOrder.php | 6 ++ .../model/store/order/StoreOrderInterest.php | 12 +++ .../order/StoreOrderInterestRepository.php | 10 +++ .../store/order/StoreOrderRepository.php | 66 +++++++++++++++ app/controller/api/store/order/StoreOrder.php | 18 ++++ crmeb/services/payTool/Balance.php | 82 +++++++++++++++++++ crmeb/services/payTool/PayTool.php | 9 +- route/api.php | 1 + 8 files changed, 197 insertions(+), 7 deletions(-) create mode 100644 crmeb/services/payTool/Balance.php diff --git a/app/common/model/store/order/StoreGroupOrder.php b/app/common/model/store/order/StoreGroupOrder.php index 9357eaed..8c6b7cf4 100644 --- a/app/common/model/store/order/StoreGroupOrder.php +++ b/app/common/model/store/order/StoreGroupOrder.php @@ -110,4 +110,10 @@ class StoreGroupOrder extends BaseModel } return $params; } + + public function interest() + { + return $this->hasOne(StoreOrderInterest::class, 'group_order_id', 'group_order_id'); + } + } diff --git a/app/common/model/store/order/StoreOrderInterest.php b/app/common/model/store/order/StoreOrderInterest.php index 64cd7c14..4793a7ed 100644 --- a/app/common/model/store/order/StoreOrderInterest.php +++ b/app/common/model/store/order/StoreOrderInterest.php @@ -20,4 +20,16 @@ class StoreOrderInterest extends BaseModel return 'store_order_interest'; } + /** + * 计算利息 + * @return string + */ + public function calculateInterest() + { + $days = ceil((time() - strtotime($this->start_time)) / 86400); + $days = max($days ,0); + $money = bcmul($this->total_price, $this->rate, 2); + return bcmul($days, $money, 2); + } + } diff --git a/app/common/repositories/store/order/StoreOrderInterestRepository.php b/app/common/repositories/store/order/StoreOrderInterestRepository.php index dd024ead..fdfecf52 100644 --- a/app/common/repositories/store/order/StoreOrderInterestRepository.php +++ b/app/common/repositories/store/order/StoreOrderInterestRepository.php @@ -15,4 +15,14 @@ class StoreOrderInterestRepository extends BaseRepository return $model->insert($data); } + public function getByGroupOrder($groupOrderId) + { + return StoreOrderInterest::where('group_order_id', $groupOrderId)->find(); + } + + public function getByOrder($orderId) + { + return StoreOrderInterest::where('order_id', $orderId)->find(); + } + } diff --git a/app/common/repositories/store/order/StoreOrderRepository.php b/app/common/repositories/store/order/StoreOrderRepository.php index 35490fe1..d5632846 100644 --- a/app/common/repositories/store/order/StoreOrderRepository.php +++ b/app/common/repositories/store/order/StoreOrderRepository.php @@ -14,6 +14,7 @@ namespace app\common\repositories\store\order; use app\common\dao\store\order\StoreOrderDao; use app\common\model\store\order\StoreGroupOrder; use app\common\model\store\order\StoreOrder; +use app\common\model\store\order\StoreOrderInterest; use app\common\model\user\User; use app\common\repositories\BaseRepository; use app\common\repositories\delivery\DeliveryOrderRepository; @@ -2426,4 +2427,69 @@ class StoreOrderRepository extends BaseRepository return true; } + /** + * 订单结算 + * @param $id + * @param $type + * @param $user + * @return array + * @throws Exception + */ + public function settle($id, $type, $user) + { + /** @var StoreGroupOrderRepository $groupOrderRepository */ + $groupOrderRepository = app()->make(StoreGroupOrderRepository::class); + $groupOrderRepository->getAll = true; + Db::startTrans(); + try { + $groupOrder = $groupOrderRepository->detail($user['uid'], $id, false); + if (!$groupOrder) { + throw new Exception('订单不存在或已支付'); + } + if (!$groupOrder->interest || $groupOrder->interest->status == StoreOrderInterest::STATUS_SETTLED) { + throw new Exception('订单无需结算'); + } + $interest = $groupOrder->interest->calculateInterest(); + $payMoney = bcadd($groupOrder->interest->total_price, $interest, 2); + $result = true; + $data = ['type' => $type, 'order_id' => $groupOrder->group_order_id, 'paid' => true]; + if ($payMoney > 0) { + if (!in_array($type, ['balance', 'scrcu'])) { + if (systemConfig('open_wx_combine')) { + $service = new CombinePayService($type, $groupOrder->getCombinePayParams()); + } else { + $service = new PayService($type, $groupOrder->getPayParams($type === 'alipay' ? request()->param('return_url') : '')); + } + $result = $service->pay($user); + $data = array_merge($data, $result, ['paid' => false]); + } else { + $payTool = PayTool::instance($type); + $groupOrder->pay_price = $payMoney; + $result = $payTool->pay($groupOrder); + } + } + if ($result === true) { + $groupOrder->interest->status = StoreOrderInterest::STATUS_SETTLED; + $groupOrder->interest->settle_time = date('Y-m-d H:i:s'); + $groupOrder->interest->save(); + + /** @var UserBillRepository $userBillRepository */ + $userBillRepository = app()->make(UserBillRepository::class); + $userBillRepository->decBill($user['uid'], 'now_money', 'pay_product', [ + 'link_id' => $groupOrder['group_order_id'], + 'status' => 1, + 'title' => '购买商品', + 'number' => $groupOrder['pay_price'], + 'mark' => '余额支付支付' . floatval($groupOrder['pay_price']) . '元购买商品', + 'balance' => $user->now_money + ]); + } + Db::commit(); + return $data; + } catch (\Exception $e) { + Db::rollback(); + throw new Exception($e->getMessage()); + } + } + } diff --git a/app/controller/api/store/order/StoreOrder.php b/app/controller/api/store/order/StoreOrder.php index fb441cca..52981133 100644 --- a/app/controller/api/store/order/StoreOrder.php +++ b/app/controller/api/store/order/StoreOrder.php @@ -298,4 +298,22 @@ class StoreOrder extends BaseController $res = $orderRepository->show($id, $this->request->uid()); return app('json')->success($res); } + + /** + * 订单结算 + * @return mixed + * @throws \Psr\SimpleCache\InvalidArgumentException + */ + public function settle() + { + $id = $this->request->param('id/d'); + $type = $this->request->param('type'); + try { + $data = $this->repository->settle($id, $type, $this->request->userInfo()); + return app('json')->success('success', $data); + } catch (\Exception $e) { + return app('json')->fail($e->getMessage()); + } + } + } diff --git a/crmeb/services/payTool/Balance.php b/crmeb/services/payTool/Balance.php new file mode 100644 index 00000000..b7d0bd25 --- /dev/null +++ b/crmeb/services/payTool/Balance.php @@ -0,0 +1,82 @@ +userInfo(); + if (!systemConfig('yue_pay_status')) { + throw new \Exception('未开启余额支付'); + } + if ($user['now_money'] < $order['pay_price']) { + throw new \Exception('余额不足,请更换支付方式'); + } + $user->now_money = bcsub($user->now_money, $order['pay_price'], 2); + if (!$user->save()) { + throw new \Exception('用户余额扣减失败'); + } + return true; + } + + /** + * 查询 + * @param $order + * @return string + * @throws \Exception + */ + public function query($order) + { + } + + /** + * 退款 + * @param $order + * @return string + * @throws \Exception + */ + public function refund($order) + { + } + + /** + * 发起请求 + * @param $body + * @return string + * @throws \Exception + */ + public function request($body) + { + } + + public function success() + { + } + + public function callback($request = null) + { + } + + public function refundQuery($refundOrder) + { + } + + public function transfer($withdraw) + { + } + +} \ No newline at end of file diff --git a/crmeb/services/payTool/PayTool.php b/crmeb/services/payTool/PayTool.php index 657d09fc..ff29b32b 100644 --- a/crmeb/services/payTool/PayTool.php +++ b/crmeb/services/payTool/PayTool.php @@ -7,21 +7,16 @@ abstract class PayTool public $config; public $error = ['success' => false]; - const Scrcu = 'scrcu'; - - const ClassMap = [ - self::Scrcu => Scrcu::class, - ]; /** * @param $name * @param $params - * @return mixed|Scrcu + * @return mixed|PayTool * @throws \Exception */ public static function instance($name, $params = []) { - $class = self::ClassMap[$name]; + $class = 'crmeb\services\payTool\\' . ucfirst($name); if (class_exists($class)) { return new $class($params); } diff --git a/route/api.php b/route/api.php index 144ef46f..72ba6e29 100644 --- a/route/api.php +++ b/route/api.php @@ -90,6 +90,7 @@ Route::group('api/', function () { Route::get('verify_code/:id', '/verifyCode'); Route::post('receipt/:id', '/createReceipt'); Route::get('delivery/:id', '/getOrderDelivery'); + Route::post('settle', '/settle'); })->prefix('api.store.order.StoreOrder'); // 预售 From 982e81f30fdee11eb3b87758ecd36e08acd277c6 Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Wed, 28 Jun 2023 16:45:48 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=81=E5=85=89push=20?= =?UTF-8?q?SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vendor/composer/autoload_psr4.php | 1 + vendor/composer/autoload_static.php | 5 + vendor/composer/installed.json | 50 ++ vendor/composer/installed.php | 21 +- vendor/jpush/jpush/.gitignore | 18 + vendor/jpush/jpush/.travis.yml | 13 + vendor/jpush/jpush/LICENSE | 21 + vendor/jpush/jpush/README.md | 121 +++ vendor/jpush/jpush/autoload.php | 10 + vendor/jpush/jpush/composer.json | 31 + vendor/jpush/jpush/doc/api.md | 494 ++++++++++++ vendor/jpush/jpush/doc/grouppush.md | 28 + vendor/jpush/jpush/doc/http2.md | 56 ++ vendor/jpush/jpush/examples/admin_example.php | 14 + .../jpush/examples/batch_push_example.php | 35 + vendor/jpush/jpush/examples/cid_example.php | 7 + .../jpush/jpush/examples/config.php.example | 10 + .../examples/devices/delete_alias_example.php | 5 + .../examples/devices/delete_tag_example.php | 5 + .../devices/get_alias_devices_example.php | 6 + .../examples/devices/get_devices_example.php | 6 + .../devices/get_devices_status_example.php | 13 + .../examples/devices/get_tags_example.php | 6 + .../devices/update_device_example.php | 56 ++ .../examples/devices/update_tag_example.php | 29 + .../jpush/examples/grouppush_example.php | 24 + .../jpush/examples/huawei_push_example.php | 36 + vendor/jpush/jpush/examples/push_example.php | 140 ++++ .../reports/messages_detail_example.php | 5 + .../reports/received_detail_example.php | 5 + .../jpush/jpush/examples/schedule_example.php | 26 + vendor/jpush/jpush/examples/zone_examples.php | 24 + vendor/jpush/jpush/phpunit.xml.dist | 15 + vendor/jpush/jpush/src/JPush/AdminClient.php | 42 + vendor/jpush/jpush/src/JPush/Client.php | 71 ++ vendor/jpush/jpush/src/JPush/Config.php | 16 + .../jpush/jpush/src/JPush/DevicePayload.php | 224 ++++++ .../Exceptions/APIConnectionException.php | 9 + .../JPush/Exceptions/APIRequestException.php | 36 + .../src/JPush/Exceptions/JPushException.php | 9 + .../JPush/Exceptions/ServiceNotAvaliable.php | 25 + vendor/jpush/jpush/src/JPush/Http.php | 139 ++++ vendor/jpush/jpush/src/JPush/PushPayload.php | 761 ++++++++++++++++++ .../jpush/jpush/src/JPush/ReportPayload.php | 109 +++ .../jpush/jpush/src/JPush/SchedulePayload.php | 182 +++++ vendor/jpush/jpush/src/JPush/version.php | 4 + .../jpush/tests/JPush/DevicePayloadTest.php | 131 +++ .../jpush/tests/JPush/PushPayloadTest.php | 315 ++++++++ .../jpush/tests/JPush/ReportPayloadTest.php | 77 ++ .../jpush/tests/JPush/SchedulePayloadTest.php | 18 + vendor/jpush/jpush/tests/bootstrap.php | 8 + 51 files changed, 3506 insertions(+), 6 deletions(-) create mode 100644 vendor/jpush/jpush/.gitignore create mode 100644 vendor/jpush/jpush/.travis.yml create mode 100644 vendor/jpush/jpush/LICENSE create mode 100644 vendor/jpush/jpush/README.md create mode 100644 vendor/jpush/jpush/autoload.php create mode 100644 vendor/jpush/jpush/composer.json create mode 100644 vendor/jpush/jpush/doc/api.md create mode 100644 vendor/jpush/jpush/doc/grouppush.md create mode 100644 vendor/jpush/jpush/doc/http2.md create mode 100644 vendor/jpush/jpush/examples/admin_example.php create mode 100644 vendor/jpush/jpush/examples/batch_push_example.php create mode 100644 vendor/jpush/jpush/examples/cid_example.php create mode 100644 vendor/jpush/jpush/examples/config.php.example create mode 100644 vendor/jpush/jpush/examples/devices/delete_alias_example.php create mode 100644 vendor/jpush/jpush/examples/devices/delete_tag_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_alias_devices_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_devices_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_devices_status_example.php create mode 100644 vendor/jpush/jpush/examples/devices/get_tags_example.php create mode 100644 vendor/jpush/jpush/examples/devices/update_device_example.php create mode 100644 vendor/jpush/jpush/examples/devices/update_tag_example.php create mode 100644 vendor/jpush/jpush/examples/grouppush_example.php create mode 100644 vendor/jpush/jpush/examples/huawei_push_example.php create mode 100644 vendor/jpush/jpush/examples/push_example.php create mode 100644 vendor/jpush/jpush/examples/reports/messages_detail_example.php create mode 100644 vendor/jpush/jpush/examples/reports/received_detail_example.php create mode 100644 vendor/jpush/jpush/examples/schedule_example.php create mode 100644 vendor/jpush/jpush/examples/zone_examples.php create mode 100644 vendor/jpush/jpush/phpunit.xml.dist create mode 100644 vendor/jpush/jpush/src/JPush/AdminClient.php create mode 100644 vendor/jpush/jpush/src/JPush/Client.php create mode 100644 vendor/jpush/jpush/src/JPush/Config.php create mode 100644 vendor/jpush/jpush/src/JPush/DevicePayload.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php create mode 100644 vendor/jpush/jpush/src/JPush/Exceptions/ServiceNotAvaliable.php create mode 100644 vendor/jpush/jpush/src/JPush/Http.php create mode 100644 vendor/jpush/jpush/src/JPush/PushPayload.php create mode 100644 vendor/jpush/jpush/src/JPush/ReportPayload.php create mode 100644 vendor/jpush/jpush/src/JPush/SchedulePayload.php create mode 100644 vendor/jpush/jpush/src/JPush/version.php create mode 100644 vendor/jpush/jpush/tests/JPush/DevicePayloadTest.php create mode 100644 vendor/jpush/jpush/tests/JPush/PushPayloadTest.php create mode 100644 vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php create mode 100644 vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php create mode 100644 vendor/jpush/jpush/tests/bootstrap.php diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 6b97c9c3..b1e5b2a1 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -54,6 +54,7 @@ return array( 'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'), 'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'), 'Joypack\\Tencent\\Map\\' => array($vendorDir . '/joypack/tencent-map/src'), + 'JPush\\' => array($vendorDir . '/jpush/jpush/src/JPush'), 'Intervention\\Image\\' => array($vendorDir . '/intervention/image/src/Intervention/Image'), 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'), 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 61d2fd4a..ef3ac0f7 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -172,6 +172,7 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 'J' => array ( 'Joypack\\Tencent\\Map\\' => 20, + 'JPush\\' => 6, ), 'I' => array ( @@ -422,6 +423,10 @@ class ComposerStaticInitb1229d2685c190533aa1234015613f09 array ( 0 => __DIR__ . '/..' . '/joypack/tencent-map/src', ), + 'JPush\\' => + array ( + 0 => __DIR__ . '/..' . '/jpush/jpush/src/JPush', + ), 'Intervention\\Image\\' => array ( 0 => __DIR__ . '/..' . '/intervention/image/src/Intervention/Image', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index ab8fbb6f..c0579459 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1614,6 +1614,56 @@ ], "install-path": "../joypack/tencent-map" }, + { + "name": "jpush/jpush", + "version": "v3.6.8", + "version_normalized": "3.6.8.0", + "source": { + "type": "git", + "url": "https://github.com/jpush/jpush-api-php-client.git", + "reference": "ebb191e8854a35c3fb7a6626028b3a23132cbe2c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jpush/jpush-api-php-client/zipball/ebb191e8854a35c3fb7a6626028b3a23132cbe2c", + "reference": "ebb191e8854a35c3fb7a6626028b3a23132cbe2c", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "time": "2021-08-12T07:43:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "JPush\\": "src/JPush/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "JPush", + "email": "support@jpush.cn", + "homepage": "https://www.jpush.cn/", + "role": "Developer" + } + ], + "description": "JPush API PHP Client", + "homepage": "https://github.com/jpush/jpush-api-php-client", + "support": { + "issues": "https://github.com/jpush/jpush-api-php-client/issues", + "source": "https://github.com/jpush/jpush-api-php-client/tree/v3.6.8" + }, + "install-path": "../jpush/jpush" + }, { "name": "khanamiryan/qrcode-detector-decoder", "version": "1.0.3", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index ff26d7ea..e5f2f7ee 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'topthink/think', - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => NULL, + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => 'c67d617fe67984f87270190027f6c00f2e447c7c', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -367,6 +367,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'jpush/jpush' => array( + 'pretty_version' => 'v3.6.8', + 'version' => '3.6.8.0', + 'reference' => 'ebb191e8854a35c3fb7a6626028b3a23132cbe2c', + 'type' => 'library', + 'install_path' => __DIR__ . '/../jpush/jpush', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'khanamiryan/qrcode-detector-decoder' => array( 'pretty_version' => '1.0.3', 'version' => '1.0.3.0', @@ -863,9 +872,9 @@ 'dev_requirement' => false, ), 'topthink/think' => array( - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => NULL, + 'pretty_version' => 'dev-master', + 'version' => 'dev-master', + 'reference' => 'c67d617fe67984f87270190027f6c00f2e447c7c', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/vendor/jpush/jpush/.gitignore b/vendor/jpush/jpush/.gitignore new file mode 100644 index 00000000..72d22537 --- /dev/null +++ b/vendor/jpush/jpush/.gitignore @@ -0,0 +1,18 @@ +*.pyc +log/ +build/ +bin/ +.pydevproject +.tar +.zip +.buildpath +.project +.settings/ +.idea +composer.lock +vendor/ +*.log +vendor.tar.gz +composer.phar +vendor.zip +examples/config.php diff --git a/vendor/jpush/jpush/.travis.yml b/vendor/jpush/jpush/.travis.yml new file mode 100644 index 00000000..b560f04c --- /dev/null +++ b/vendor/jpush/jpush/.travis.yml @@ -0,0 +1,13 @@ +language: php + +php: + - '5.3' + - '5.4' + - '5.5' + - '5.6' + - '7.0' + +before_script: + - composer install +script: + - ./vendor/bin/phpunit tests diff --git a/vendor/jpush/jpush/LICENSE b/vendor/jpush/jpush/LICENSE new file mode 100644 index 00000000..99ff8e71 --- /dev/null +++ b/vendor/jpush/jpush/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 极光 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/jpush/jpush/README.md b/vendor/jpush/jpush/README.md new file mode 100644 index 00000000..3e48c541 --- /dev/null +++ b/vendor/jpush/jpush/README.md @@ -0,0 +1,121 @@ +# JPush API PHP Client + +这是 JPush REST API 的 PHP 版本封装开发包,是由极光推送官方提供的,一般支持最新的 API 功能。 + +对应的 REST API 文档: https://docs.jiguang.cn/jpush/server/push/server_overview/ + +> 支持的 PHP 版本: 5.3.3 ~ 5.6.x, 7.x + +> 若需要兼容 PHP 5.3.3 以下版本,可以使用 [v3 分支的代码](https://github.com/jpush/jpush-api-php-client/tree/v3)。 +因为运行 Composer 需要 PHP 5.3.2+ 以上版本,所以其不提供 Composer 支持, +也可以[点击链接](https://github.com/jpush/jpush-api-php-client/releases)下载 v3.4.x 版本源码。 + +## Installation + +#### 使用 Composer 安装 + +- 执行 `$ php composer.phar install` 或 `$ composer install` 进行安装。 + +#### 直接下载源码安装 + +> 直接下载源代码也是一种安装 SDK 的方法,不过因为有版本更新的维护问题,所以这种安装方式**十分不推荐**,但由于种种原因导致无法使用 Composer,所以我们也提供了这种情况下的备选方案。 + +- 下载源代码包,解压到项目中 +- 在项目中引入 autoload: + +```php +require 'path_to_sdk/autoload.php'; +``` + +## Usage + +- [Init API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#init-api) +- [Push API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#push-api) +- [Report API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#report-api) +- [Device API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#device-api) +- [Schedule API](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#schedule-api) +- [Exception Handle](https://github.com/jpush/jpush-api-php-client/blob/master/doc/api.md#schedule-api) +- [HTTP/2 Support](https://github.com/jpush/jpush-api-php-client/blob/master/doc/http2.md) +- [Group Push](https://github.com/jpush/jpush-api-php-client/blob/master/doc/grouppush.md) + +#### 初始化 + +```php +use JPush\Client as JPush; +... +... + + $client = new JPush($app_key, $master_secret); + +... +``` + +OR + +```php +$client = new \JPush\Client($app_key, $master_secret); +``` + +#### 简单推送 + +```php +$client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello, JPush') + ->send(); +``` + +#### 异常处理 + +```php +$pusher = $client->push(); +$pusher->setPlatform('all'); +$pusher->addAllAudience(); +$pusher->setNotificationAlert('Hello, JPush'); +try { + $pusher->send(); +} catch (\JPush\Exceptions\JPushException $e) { + // try something else here + print $e; +} +``` + +## Examples + +**注意: 这只是使用样例, 不应该直接用于实际环境中!!** + +在下载的中的 [examples](https://github.com/jpush/jpush-api-php-client/tree/master/examples) 文件夹有简单示例代码, 开发者可以参考其中的样例快速了解该库的使用方法。 + +**简单使用方法** + +先填写对应的appKey和masterSecret,可以额外设定Registration_id。 + +若要运行 push_example.php 中的示例代码: + +``` bash +# 假定当前目录为 JPush 源码所在的根目录 +$ php examples/push_example.php +``` +> 同时也可编辑相关的示例文件,更改参数查看执行效果 + +## Testing + +```bash +# 编辑 tests/bootstrap.php 文件,填入必须的变量值 +# OR 设置相应的环境变量 + +# 运行全部测试用例 +$ composer tests + +# 运行某一具体测试用例 +$ composer tests/JPush/xxTest.php +``` + +## Contributing + +Bug reports and pull requests are welcome on GitHub at https://github.com/jpush/jpush-api-php-client. + +## License + +The library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). diff --git a/vendor/jpush/jpush/autoload.php b/vendor/jpush/jpush/autoload.php new file mode 100644 index 00000000..d27a7d84 --- /dev/null +++ b/vendor/jpush/jpush/autoload.php @@ -0,0 +1,10 @@ +=5.3.3", + "ext-curl": "*" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "autoload" : { + "psr-4": {"JPush\\": "src/JPush/"} + }, + "autoload-dev": { + "psr-4": { "JPush\\Tests\\": "tests/" } + }, + "scripts": { + "test": "vendor/bin/phpunit" + } +} diff --git a/vendor/jpush/jpush/doc/api.md b/vendor/jpush/jpush/doc/api.md new file mode 100644 index 00000000..d84850dc --- /dev/null +++ b/vendor/jpush/jpush/doc/api.md @@ -0,0 +1,494 @@ +# 目录 + +- [Init API](#init-api) +- [Push API](#push-api) +- [Report API](#report-api) +- [Device API](#device-api) +- [Schedule API](#schedule-api) +- [Exception Handle](#schedule-api) + +> **注:PHP SDK 全面支持 namespaces 但为方便表达,以下例子都不使用 use 语句** + +## Init API + +在调用推送之前,我们必须先初始化 JPushClient,调用以下代码可以进行快速初始化: + +```php +$client = new \JPush\Client($app_key, $master_secret); +``` + +在初始化 JPushClient 的时候,可以指定**日志路径**: + +```php +$client = new \JPush\Client($app_key, $master_secret, $log_path); +``` +> 默认日志路径为 `./jpush.log`,即保存在当前运行目录,如果想关闭日志,可以指定为 `null`。 + +## Push API + +在初始化 JPushClient 后,调用以下代码将返回一个推送 Payload 构建器,它提供丰富的API来帮助你构建 PushPayload。 + +```php +$push = $client->push(); +``` + +通过 [JPush Push API](https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/) 我们知道,一个 PushPayload 是由以下几个部分构成的: + +- Cid +- Platform +- Audience +- Notification +- Message +- SmsContent +- Options + +#### Cid + +```php +$push->setCid($cid); +``` + +#### Platform + +```php +$push->setPlatform('all'); +// OR +$push->setPlatform('ios', 'android'); +// OR +$push->setPlatform(['ios', 'android']); +``` + +#### Audience + +```php +$push->addAllAudience(); +``` + +```php +$push->addTag('tag1'); +// OR +$push->addTag(['tag1', 'tag2']); +``` + +其他诸如 `addAlias()`, `addRegistrationId()`, `addTagAnd()`, `addTagNot()`, `addSegmentId()`, `addAbtest()` 的使用方法与 `addTag()` 类似,在此不做赘述。 + +#### Notification + +```php +// 简单地给所有平台推送相同的 alert 消息 +$push->setNotificationAlert('alert'); +``` + +**iOS Notification** + +```php +// iosNotification($alert = '', array $notification = array()) +// 数组 $notification 的键支持 'sound', 'badge', 'content-available', 'mutable-content', category', 'extras', 'thread-id' 中的一个或多个 + +// 调用示例 +$push->iosNotification(); +// OR +$push->iosNotification('hello'); +// OR +$push->iosNotification('hello', [ + 'sound' => 'sound', + 'badge' => '+1', + 'extras' => [ + 'key' => 'value' + ] +]); +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| alert |表示通知内容,会覆盖上级统一指定的 alert 信息;默认内容可以为空字符串,表示不展示到通知栏, 支持字符串和数组两种形式 | +| sound | 表示通知提示声音,默认填充为空字符串 | +| badge | 表示应用角标,把角标数字改为指定的数字;为 0 表示清除,支持 '+1','-1' 这样的字符串,表示在原有的 badge 基础上进行增减,默认填充为 '+1' | +| content-available | 表示推送唤醒,仅接受 true 表示为 Background Remote Notification,若不填默认表示普通的 Remote Notification | +| mutable-content | 表示通知扩展, 仅接受 true 表示支持 iOS10 的 UNNotificationServiceExtension, 若不填默认表示普通的 Remote Notification | +| category | IOS8才支持。设置 APNs payload 中的 'category' 字段值 | +| thread-id | 表示通知分组,ios 的远程通知通过该属性来对通知进行分组,同一个 thread-id 的通知归为一组 | +| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | + +**Android Notification** + +```php +// androidNotification($alert = '', array $notification = array()) +// 调用示例同 IOS,数组 $notification 的键支持 'title', 'builder_id', 'priority', 'category', 'style', 'alert_type', 'big_text', 'inbox', 'big_pic_path', 'large_icon', 'intent', 'extras' 中的一个或多个 +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| alert | 表示通知内容,会覆盖上级统一指定的 alert 信息;默认内容可以为空字符串,表示不展示到通知栏 | +| title | 表示通知标题,会替换通知里原来展示 App 名称的地方 | +| builder_id | 表示通知栏样式 ID | +| priority | 表示通知栏展示优先级,默认为 0,范围为 -2~2 ,其他值将会被忽略而采用默认值 | +| category | 表示通知栏条目过滤或排序,完全依赖 rom 厂商对 category 的处理策略 | +| style | 表示通知栏样式类型,默认为 0,还有1,2,3可选,用来指定选择哪种通知栏样式,其他值无效。有三种可选分别为 bigText=1,Inbox=2,bigPicture=3 | +| alert_type | 表示通知提醒方式, 可选范围为 -1~7 ,对应 Notification.DEFAULT_ALL = -1 或者 Notification.DEFAULT_SOUND = 1, Notification.DEFAULT_VIBRATE = 2, Notification.DEFAULT_LIGHTS = 4 的任意 “or” 组合。默认按照 -1 处理。 | +| big_text | 表示大文本通知栏样式,当 style = 1 时可用,内容会被通知栏以大文本的形式展示出来,支持 api 16 以上的 rom | +| inbox | 表示文本条目通知栏样式,接受一个数组,当 style = 2 时可用,数组的每个 key 对应的 value 会被当作文本条目逐条展示,支持 api 16 以上的 rom | +| big_pic_path | 表示大图片通知栏样式,当 style = 3 时可用,可以是网络图片 url,或本地图片的 path,目前支持 .jpg 和 .png 后缀的图片。图片内容会被通知栏以大图片的形式展示出来。如果是 http/https 的 url,会自动下载;如果要指定开发者准备的本地图片就填 sdcard 的相对路径,支持 api 16 以上的 rom | +| large_icon | 表示通知栏大图标,图标路径可以是以 http 或 https 开头的网络图片,如:"http:jiguang.cn/logo.png",图标大小不超过 30k; 也可以是位于 drawable 资源文件夹的图标路径,如:"R.drawable.lg_icon";| +| intent | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | +| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | + +**WinPhone Notification** + +```php +$push->addWinPhoneNotification($alert=null, $title=null, $_open_page=null, $extras=null) +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| alert | 表示通知内容,会覆盖上级统一指定的 alert 信息;内容为空则不展示到通知栏 | +| title | 通知标题,会填充到 toast 类型 text1 字段上 | +| _open_page | 点击打开的页面名称 | + +#### Message + +```php +// message($msg_content, array $msg = array()) +// 数组 $msg 的键支持 'title', 'content_type', 'extras' 中的一个或多个 + +// 调用示例 +$push->message('Hello JPush'); +// OR +$push->message('Hello JPush', [ + 'title' => 'Hello', + 'content_type' => 'text', + 'extras' => [ + 'key' => 'value' + ] +]); +``` + +参数说明: + +| 参数 | 说明 | +| --- | --- | +| msg_content | 消息内容本身 | +| title | 消息标题 | +| content_type | 消息内容类型 | +| extras | 表示扩展字段,接受一个数组,自定义 Key/value 信息以供业务使用 | + +#### Sms Message + +```php +$push->setSms($delay_time, $temp_id, array $temp_para = []) +``` + +参数说明: +* delay_time: 表示短信发送的延迟时间,单位为秒,不能超过 24 小时(即大于等于 0 小于等于 86400)。仅对 android 平台有效。 +* temp_id: 短信补充的内容模板 ID。没有填写该字段即表示不使用短信补充功能。 +* temp_para: 短信模板中的参数 + +##### 已弃用 + +```php +$push->setSmsMessage($content, $delay_time) +``` + +参数说明: +* content: 短信文本,不超过 480 字符 +* delay_time: 表示短信发送的延迟时间,单位为秒,不能超过 24 小时(即大于等于 0 小于等于 86400)。仅对 android 平台有效。默认为 0,表示立即发送短信 + +#### Options + +```php +// options(array $opts = array()) +// 数组 $opts 的键支持 'sendno', 'time_to_live', 'override_msg_id', 'apns_production', 'big_push_duration', 'apns_collapse_id' 中的一个或多个 +``` + +参数说明: + +| 可选项 | 说明 | +| --- | --- | +| sendno | 表示推送序号,纯粹用来作为 API 调用标识,API 返回时被原样返回,以方便 API 调用方匹配请求与返回 | +| time_to_live | 表示离线消息保留时长(秒),推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到 | +| override_msg_id | 表示要覆盖的消息ID,如果当前的推送要覆盖之前的一条推送,这里填写前一条推送的 msg_id 就会产生覆盖效果 | +| apns_production | 表示 APNs 是否生产环境,True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送开发环境 | +| apns_collapse_id | APNs 新通知如果匹配到当前通知中心有相同 apns-collapse-id 字段的通知,则会用新通知内容来更新它,并使其置于通知中心首位;collapse id 长度不可超过 64 bytes| +| big_push_duration | 表示定速推送时长(分钟),又名缓慢推送,把原本尽可能快的推送速度,降低下来,给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为1400.未设置则不是定速推送 | + +#### Common Method + +```php +// 发送推送 +// 该方法内部将自动调用构建方法获得当前构建对象,并转化为 JSON 向 JPush 服务器发送请求 +$push->send(); +``` + +> 构建 PushPayload 的 API 每一次都会返回自身的引用,所以我们可用使用链式调用的方法提高代码的简洁性,如: + +```php +$response = $push() + ->setCid('xxxxxx') + ->setPlatform(['ios', 'android']) + ->addTag(['tag1', 'tag2']) + ->setNotificationAlert('Hello, JPush') + ->iosNotification('hello', [ + 'sound' => 'sound', + 'badge' => '+1', + 'extras' => [ + 'key' => 'value' + ] + ]) + ->androidNotification('hello') + ->message('Hello JPush', [ + 'title' => 'Hello', + 'content_type' => 'text', + 'extras' => [ + 'key' => 'value' + ] + ]) + ->send(); + +// OR 也可以提前准备好所有的参数,然后链式调用,这样代码可读性更好一点 +$cid = 'xxxxxx'; +$platform = array('ios', 'android'); +$alert = 'Hello JPush'; +$tag = array('tag1', 'tag2'); +$regId = array('rid1', 'rid2'); +$ios_notification = array( + 'sound' => 'hello jpush', + 'badge' => 2, + 'content-available' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), +); +$android_notification = array( + 'title' => 'hello jpush', + 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), +); +$content = 'Hello World'; +$message = array( + 'title' => 'hello jpush', + 'content_type' => 'text', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), +); +$options = array( + 'sendno' => 100, + 'time_to_live' => 100, + 'override_msg_id' => 100, + 'big_push_duration' => 100 +); +$response = $push->setCid($cid) + ->setPlatform($platform) + ->addTag($tag) + ->addRegistrationId($regId) + ->iosNotification($alert, $ios_notification) + ->androidNotification($alert, $android_notification) + ->message($content, $message) + ->options($options) + ->send(); +``` + +#### 获取 Cid + +```php +$push->getCid($count = 1, $type = 'push'); +``` + +## Report API + +```php + $report = $client->report(); + ``` + +#### 获取送达统计 + +```php +$report->getReceived('msg_id'); +// OR +$report->getReceived(['msg_id1', 'msg_id2']); +``` + +#### 送达状态查询 + +```php +$msg_id0 = 66666666666; +$report->getMessageStatus($msg_id0, 'rid0'); +# OR +$report->getMessageStatus($msg_id0, ['rid0', 'rid1']); +#OR +$report->getMessageStatus($msg_id0, ['rid0', 'rid1'], '2017-12-21'); +``` + +#### 获取消息统计 + +```php +// getMessages(getMessages($msgIds)); +// 消息统计与送达统计一样,接受一个数组的参数,在这里不做赘述 +``` + +#### 获取用户统计 + +调用一下代码可以获得用户统计 + +```php +$report->getUsers($time_unit, $start, $duration) +``` + +参数说明: + +- time_unit:`String` 时间单位, 可取值HOUR, DAY, MONTH +- start:`String` 起始时间 + - 如果单位是小时,则起始时间是小时(包含天),格式例:2014-06-11 09 + - 如果单位是天,则起始时间是日期(天),格式例:2014-06-11 + - 如果单位是月,则起始时间是日期(月),格式例:2014-06 +- duration:`String` 持续时长 + - 如果单位是天,则是持续的天数。以此类推 + - 只支持查询60天以内的用户信息,对于time_unit为HOUR的,只支持输出当天的统计结果。 + +## Device API + +```php +$device = $client->device(); +``` + +#### 操作 Device(registration_id) + +```php +// 查询指定设备的别名与标签 +$device->getDevices($registration_id); + + +// 更新指定设备的别名与标签 + +// 更新 Alias +$device->updateAlias($registration_id, 'alias'); +// 添加 tag, 支持字符串和数组两种参数 +$device->addTags($registration_id, 'tag'); +// OR +$device->addTags($registration_id, ['tag1', 'tag2']); +// 移除 tag,支持字符串和数组两种参数 +$device->removeTags($registration_id, 'tags'); +// OR +$device->removeTags($registration_id, ['tag1', 'tag2']); +// 清空所有 tag +$device->clearTags($registration_id); + +// 更新 mobile +$device->updateMoblie($registration_id, '13800138000'); +// 取消手机绑定 +$device->clearMobile($registration_id); + +// getDevicesStatus($registrationId) +// 获取在线用户的登录状态(VIP专属接口),支持字符串和数组两种参数 +$device->getDevicesStatus('rid'); +// OR +$device->getDevicesStatus(['rid1', 'rid2']); +``` + +#### 操作标签 + +```php +// 获取标签列表 +$device->getTags() + +// 判断指定设备是否在指定标签之下 +$device->isDeviceInTag($registrationId, $tag); + + +// 更新标签 + +// 为标签添加设备,支持字符串和数组两种参数 +$device->addDevicesToTag($tag, 'rid'); +$device->addDevicesToTag($tag, ['rid1', 'rid2']); + +// 为标签移除设备,支持字符串和数组两种参数 +$device->removeDevicesFromTag($tag, 'rid'); +$device->removeDevicesFromTag($tag, ['rid1', 'rid2']); + + +// 删除标签 +$device->deleteTag('tag'); +``` + +#### 操作别名 + +```php +// 获取指定别名下的设备 +$device->getAliasDevices('alias'); + +// 删除别名 +$device->deleteAlias('alias'); +``` + +## Schedule API + +```php +$schedule = $client->schedule(); +``` + +#### 创建定时任务 + +定时任务分为Single与Periodical两种,可以通过调用以下方法创建定时任务 + +```php +$schedule->createSingleSchedule($name, $push_payload, $trigger) +$schedule->createPeriodicalSchedule($name, $push_payload, $trigger) +``` + +参数说明: +- name: `String` 定时任务的名称 +- push_payload: `PushPayload` Push的构建对象,通过Push模块的`build()`方法获得 +- trigger: `Array` 触发器对象 + +#### 更新定时任务 + +```php +$schedule->updateSingleSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) +$schedule->updatePeriodicalSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) +``` + +#### 其他 + +```php +// 获取定时任务列表 +$schedule->getSchedules($page=1); + +// 获取指定定时任务 +$schedule->getSchedule($schedule_id); + +// 删除指定定时任务 +$schedule->deleteSchedule($schedule_id); + +// 获取定时任务对应的所有 msg_id +$schedule->getMsgIds($schedule_id); +``` + +## Exception Handle + +当 API 请求发生错误时,SDK 将抛出异常,Pushpayload 具体错误代码请参考[ API 错误代码表](https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#_19)。 +PHP SDK 主要抛出两个异常 `\JPush\Exceptions\APIConnectionException` 和 `\JPush\Exceptions\APIRequestException` 分别对应请求连接产生的异常和请求响应的异常。 +这两种异常都需要捕获,为简单起见,也可以捕获他们的父类异常 `JPush\Exceptions\JPushException`(见 README)。另外 APIRequestException 异常还提供其他方法供开发者调用。 + +```php +try { + $pusher->send(); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} +``` diff --git a/vendor/jpush/jpush/doc/grouppush.md b/vendor/jpush/jpush/doc/grouppush.md new file mode 100644 index 00000000..81fd3d65 --- /dev/null +++ b/vendor/jpush/jpush/doc/grouppush.md @@ -0,0 +1,28 @@ +# JPush Group Push + +## 获取 Group Key 和 Group Master Secret + +```php +$group_key = 'xxxx'; +$group_master_secret = 'xxxx'; +``` + +## 初始化 + +**注:Group Key 需拼接 'group-' 使用** + +```php +$client = new \JPush\Client('group-' . $group_key, $group_master_secret); +``` + +## 简单群组推送 + +```php +$client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello, JPush') + ->send(); +``` + +> [Example](https://github.com/jpush/jpush-api-php-client/blob/master/examples/push_example.php) diff --git a/vendor/jpush/jpush/doc/http2.md b/vendor/jpush/jpush/doc/http2.md new file mode 100644 index 00000000..4fe87de1 --- /dev/null +++ b/vendor/jpush/jpush/doc/http2.md @@ -0,0 +1,56 @@ +# JPush API PHP Client With HTTP/2 Support + +> JPush API PHP Client 全面支持 HTTP/2, +> **要求 PHP >= 5.5.24**, +> 但由于 libcurl 对于 HTTP/2 的实现依赖于第三方库 [nghttp2](https://github.com/nghttp2/nghttp2) 所以如果要支持 HTTP/2 需要做一些其他的配置。 + +### 安装 nghttp2 + +系统依赖仅针对 Ubuntu 14.04 LTS (trusty) 和 Debian 7.0 (wheezy) 或以上版本,其他系统版本请按照 nghttp2 的文档来操作: + +> From Ubuntu 15.10, spdylay has been available as a package named libspdylay-dev. For the earlier Ubuntu release, you need to build it yourself: http://tatsuhiro-t.github.io/spdylay/ + +详细情况请查看 [nghttp2 的文档](https://github.com/nghttp2/nghttp2#requirements)。 + +```bash +# Get build requirements +# Some of these are used for the Python bindings +# this package also installs +$ sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \ + zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \ + libjemalloc-dev cython python3-dev python-setuptools + +# Build nghttp2 from source +$ git clone https://github.com/tatsuhiro-t/nghttp2.git +$ cd nghttp2 +$ autoreconf -i +$ automake +$ autoconf +$ ./configure +$ make +$ sudo make install +``` + +### 升级 curl 至最新版本 + +```bash +$ sudo apt-get build-dep curl +# 请根据当前的 curl 官网中的最新版本(https://curl.haxx.se/download/)替换下面的相应位置 +$ wget https://curl.haxx.se/download/curl-7.x.x.tar.bz2 +$ tar -xvjf curl-7.x.x.tar.bz2 +$ cd curl-7.x.x +$ ./configure --with-nghttp2=/usr/local --with-ssl +$ make +$ sudo make install +``` + +### 测试 + +##### 命令行测试 +命令行运行 `$ curl --version`,若输出中的 Features 栏中有 `HTTP2` 一项则证明配置成功。 + +##### 样例测试 +运行样例 `$ php examples/devices/get_devices_example.php`,若输出中的 HTTP 版本是 HTTP/2 则证明已经在使用 HTTP2 发送请求和接受响应了。 + +##### 测试测试 +运行测试 `$./vendor/bin/phpunit tests/JPush/DevicePayloadTest.php`,若打印出的 http headers 中的 HTTP 版本是 HTTP/2 则证明已经在使用 HTTP2 发送请求和接受响应了。 diff --git a/vendor/jpush/jpush/examples/admin_example.php b/vendor/jpush/jpush/examples/admin_example.php new file mode 100644 index 00000000..9b955516 --- /dev/null +++ b/vendor/jpush/jpush/examples/admin_example.php @@ -0,0 +1,14 @@ +createApp('aaa', 'cn.jpush.app'); +print_r($response); + +$appKey = $response['body']['app_key']; +$response = $admin->deleteApp($appKey); +print_r($response); diff --git a/vendor/jpush/jpush/examples/batch_push_example.php b/vendor/jpush/jpush/examples/batch_push_example.php new file mode 100644 index 00000000..52b4e5e7 --- /dev/null +++ b/vendor/jpush/jpush/examples/batch_push_example.php @@ -0,0 +1,35 @@ + 'all', + 'target' => 'regid1', + 'notification' => array( + 'alert' => 'NotificationAlert1' + ) + ), + array( + 'platform' => 'all', + 'target' => 'regid2', + 'notification' => array( + 'alert' => 'NotificationAlert2' + ) + ) +); + +$push_payload = $client -> push(); +try { + $response = $push_payload -> batchPushByRegid($singlePayloads); + print_r($response); + $response = $push_payload -> batchPushByAlias($singlePayloads); + print_r($response); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/cid_example.php b/vendor/jpush/jpush/examples/cid_example.php new file mode 100644 index 00000000..97b6aeeb --- /dev/null +++ b/vendor/jpush/jpush/examples/cid_example.php @@ -0,0 +1,7 @@ +push()->getCid(); + +print_r($response); diff --git a/vendor/jpush/jpush/examples/config.php.example b/vendor/jpush/jpush/examples/config.php.example new file mode 100644 index 00000000..3d8627fb --- /dev/null +++ b/vendor/jpush/jpush/examples/config.php.example @@ -0,0 +1,10 @@ +device()->deleteAlias('alias'); +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/delete_tag_example.php b/vendor/jpush/jpush/examples/devices/delete_tag_example.php new file mode 100644 index 00000000..09a29148 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/delete_tag_example.php @@ -0,0 +1,5 @@ +device()->deleteTag('tag'); +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/get_alias_devices_example.php b/vendor/jpush/jpush/examples/devices/get_alias_devices_example.php new file mode 100644 index 00000000..707548e4 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_alias_devices_example.php @@ -0,0 +1,6 @@ +device()->getAliasDevices('alias'); +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/get_devices_example.php b/vendor/jpush/jpush/examples/devices/get_devices_example.php new file mode 100644 index 00000000..6e983c1f --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_devices_example.php @@ -0,0 +1,6 @@ +device()->getDevices($registration_id); +print_r($response); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/devices/get_devices_status_example.php b/vendor/jpush/jpush/examples/devices/get_devices_status_example.php new file mode 100644 index 00000000..47efe392 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_devices_status_example.php @@ -0,0 +1,13 @@ +device()->getDevicesStatus($registration_id); +} catch(\JPush\Exceptions\APIRequestException $e) { + print $e; + print $e->getHttpCode(); + print $e->getHeaders(); +} + +print_r($response); diff --git a/vendor/jpush/jpush/examples/devices/get_tags_example.php b/vendor/jpush/jpush/examples/devices/get_tags_example.php new file mode 100644 index 00000000..72041cf8 --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/get_tags_example.php @@ -0,0 +1,6 @@ +device()->getDevices($registration_id); +print_r($response); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/devices/update_device_example.php b/vendor/jpush/jpush/examples/devices/update_device_example.php new file mode 100644 index 00000000..51c0e88d --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/update_device_example.php @@ -0,0 +1,56 @@ +device()->getDevices($registration_id); +print "before update alias = " . $result['body']['alias'] . "\n"; + +print 'updating alias ... response = '; +$response = $client->device()->updateAlias($registration_id, 'jpush_alias'); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after update alias = " . $result['body']['alias'] . "\n\n"; + +// 添加 tag +$result = $client->device()->getDevices($registration_id); +print "before add tags = [" . implode(',', $result['body']['tags']) . "]\n"; + +print 'add tag1 tag2 ... response = '; + +$response = $client->device()->addTags($registration_id, 'tag0'); +print_r($response); + +$response = $client->device()->addTags($registration_id, ['tag1', 'tag2']); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after add tags = [" . implode(',', $result['body']['tags']) . "]\n\n"; + + +// 移除 tag +$result = $client->device()->getDevices($registration_id); +print "before remove tags = [" . implode(',', $result['body']['tags']) . "]\n"; + +print 'removing tag1 tag2 ... response = '; + +$response = $client->device()->removeTags($registration_id, 'tag0'); +print_r($response); + +$response = $client->device()->removeTags($registration_id, ['tag1', 'tag2']); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after remove tags = [" . implode(',', $result['body']['tags']) . "]\n\n"; + + +// 更新 mobile +$result = $client->device()->getDevices($registration_id); +print "before update mobile = " . $result['body']['mobile'] . "\n"; + +print 'updating mobile ... response = '; +$response = $client->device()->updateMoblie($registration_id, '13800138000'); +print_r($response); + +$result = $client->device()->getDevices($registration_id); +print "after update mobile = " . $result['body']['mobile'] . "\n\n"; \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/devices/update_tag_example.php b/vendor/jpush/jpush/examples/devices/update_tag_example.php new file mode 100644 index 00000000..a5f19bae --- /dev/null +++ b/vendor/jpush/jpush/examples/devices/update_tag_example.php @@ -0,0 +1,29 @@ +device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "before add device = " . $r . "\n"; + +print 'adding device ... response = '; +$response = $client->device()->addDevicesToTag('tag', $registration_id); +print_r($response); + +$result = $client->device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "after add tags = " . $r . "\n\n"; + +// 为一个标签删除设备 +$result = $client->device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "before remove device = " . $r . "\n"; + +print 'removing device ... response = '; +$response = $client->device()->removeDevicesFromTag('tag', $registration_id); +print_r($response); + +$result = $client->device()->isDeviceInTag($registration_id, 'tag'); +$r = $result['body']['result'] ? 'true' : 'false'; +print "after remove device = " . $r . "\n\n"; + diff --git a/vendor/jpush/jpush/examples/grouppush_example.php b/vendor/jpush/jpush/examples/grouppush_example.php new file mode 100644 index 00000000..4cbe45ac --- /dev/null +++ b/vendor/jpush/jpush/examples/grouppush_example.php @@ -0,0 +1,24 @@ +push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hi, JPush'); +try { + $response = $push_payload->send(); + print_r($response); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} diff --git a/vendor/jpush/jpush/examples/huawei_push_example.php b/vendor/jpush/jpush/examples/huawei_push_example.php new file mode 100644 index 00000000..c601fc68 --- /dev/null +++ b/vendor/jpush/jpush/examples/huawei_push_example.php @@ -0,0 +1,36 @@ +push() + ->setPlatform(array('ios', 'android')) + // ->addAlias('alias') + ->addTag(array('tag1', 'tag2')) + // ->addRegistrationId($registration_id) + ->setNotificationAlert('Hi, JPush') + ->androidNotification('Hello HUAWEI', array( + 'title' => 'huawei demo', + + // --------------------------------------------------- + // `uri_activity` 字段用于指定想要打开的 activity. + // 值为 activity 节点的 “android:name” 属性值。 + 'uri_activity' => 'cn.jpush.android.ui.OpenClickActivity', + // --------------------------------------------------- + + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )); + // ->send(); + print_r($payload->build()); + +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} diff --git a/vendor/jpush/jpush/examples/push_example.php b/vendor/jpush/jpush/examples/push_example.php new file mode 100644 index 00000000..3a950615 --- /dev/null +++ b/vendor/jpush/jpush/examples/push_example.php @@ -0,0 +1,140 @@ +push() +// ->setPlatform('all') +// ->addAllAudience() +// ->setNotificationAlert('Hi, JPush'); +// try { +// $response = $push_payload->send(); +// print_r($response); +// } catch (\JPush\Exceptions\APIConnectionException $e) { +// // try something here +// print $e; +// } catch (\JPush\Exceptions\APIRequestException $e) { +// // try something here +// print $e; +// } + +// 完整的推送示例 +// 这只是使用样例,不应该直接用于实际生产环境中 !! +try { + $response = $client->push() + ->setPlatform(array('ios', 'android')) + // 一般情况下,关于 audience 的设置只需要调用 addAlias、addTag、addTagAnd 或 addRegistrationId + // 这四个方法中的某一个即可,这里仅作为示例,当然全部调用也可以,多项 audience 调用表示其结果的交集 + // 即是说一般情况下,下面三个方法和没有列出的 addTagAnd 一共四个,只适用一个便可满足大多数的场景需求 + + // ->addAlias('alias') + // ->addTag(array('tag1', 'tag2')) + // ->addRegistrationId($registration_id) + ->addAllAudience() + + ->setNotificationAlert('Test custom') + ->iosNotification('Hello IOS', array( + 'sound' => 'sound.caf', + // 'badge' => '+1', + // 'content-available' => true, + // 'mutable-content' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )) + ->androidNotification('Hello Android', array( + 'title' => 'hello jpush', + // 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )) + // voip可以传输任意键值对,可用作自定义 + ->voip(array( + 'test123' => 'val1', + 'jsontest' => 2, + 'booleantest' => true + )) + ->message('message content', array( + 'title' => 'hello jpush', + // 'content_type' => 'text', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + )) + ->options(array( + // sendno: 表示推送序号,纯粹用来作为 API 调用标识, + // API 返回时被原样返回,以方便 API 调用方匹配请求与返回 + // 这里设置为 100 仅作为示例 + + // 'sendno' => 100, + + // time_to_live: 表示离线消息保留时长(秒), + // 推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。 + // 默认 86400 (1 天),最长 10 天。设置为 0 表示不保留离线消息,只有推送当前在线的用户可以收到 + // 这里设置为 1 仅作为示例 + + 'time_to_live' => 1, + + // apns_production: 表示APNs是否生产环境, + // True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送开发环境 + + // 'apns_production' => false, + + // big_push_duration: 表示定速推送时长(分钟),又名缓慢推送,把原本尽可能快的推送速度,降低下来, + // 给定的 n 分钟内,均匀地向这次推送的目标用户推送。最大值为1400.未设置则不是定速推送 + // 这里设置为 1 仅作为示例 + + // 'big_push_duration' => 1 + )) + ->setSmsMessage(array( + 'delay_time' => 60, + 'signid' => 154, + 'temp_id' => 1, + 'temp_para' => array( + 'code' => 357 + ), + 'active_filter' => false + )) + // custom可自定义最外层参数,如skd未支持部分文档功能,用户可自行写入 + // 这里仅作为例子展示 + // ->custom(array( + // 'sms_message' => array( + // 'active_filter' => false, + // 'delay_time' => 60, + // 'signid' => 154, + // 'temp_id' => 1, + // 'temp_para' => array( + // 'code' => 357 + // )), + // 'options' => array( + // 'apns_production' => false, + // 'time_to_live' => 62000, + // ) + // )) + ->send(); + print_r($response); + +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} diff --git a/vendor/jpush/jpush/examples/reports/messages_detail_example.php b/vendor/jpush/jpush/examples/reports/messages_detail_example.php new file mode 100644 index 00000000..5f7a9ae6 --- /dev/null +++ b/vendor/jpush/jpush/examples/reports/messages_detail_example.php @@ -0,0 +1,5 @@ +report()->getMessagesDetail('149646415212'); +print_r($result); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/reports/received_detail_example.php b/vendor/jpush/jpush/examples/reports/received_detail_example.php new file mode 100644 index 00000000..b2dc5da2 --- /dev/null +++ b/vendor/jpush/jpush/examples/reports/received_detail_example.php @@ -0,0 +1,5 @@ +report()->getReceivedDetail('149646415212'); +print_r($result); \ No newline at end of file diff --git a/vendor/jpush/jpush/examples/schedule_example.php b/vendor/jpush/jpush/examples/schedule_example.php new file mode 100644 index 00000000..67d60f5b --- /dev/null +++ b/vendor/jpush/jpush/examples/schedule_example.php @@ -0,0 +1,26 @@ +push() + ->setPlatform("all") + ->addAllAudience() + ->setNotificationAlert("Hi, 这是一条定时发送的消息") + ->build(); + +// 创建一个2016-12-22 13:45:00触发的定时任务 +$response = $client->schedule()->createSingleSchedule("每天14点发送的定时任务", $payload, array("time"=>"2016-12-22 13:45:00")); +print_r($response); + +// 创建一个每天14点发送的定时任务 +$response = $client->schedule()->createPeriodicalSchedule("每天14点发送的定时任务", $payload, + array( + "start"=>"2016-12-22 13:45:00", + "end"=>"2016-12-25 13:45:00", + "time"=>"14:00:00", + "time_unit"=>"DAY", + "frequency"=>1 + )); +print_r($response); + diff --git a/vendor/jpush/jpush/examples/zone_examples.php b/vendor/jpush/jpush/examples/zone_examples.php new file mode 100644 index 00000000..377f334b --- /dev/null +++ b/vendor/jpush/jpush/examples/zone_examples.php @@ -0,0 +1,24 @@ +push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hi, JPush'); +try { + $response = $push_payload->send(); + print_r($response); +} catch (\JPush\Exceptions\APIConnectionException $e) { + // try something here + print $e; +} catch (\JPush\Exceptions\APIRequestException $e) { + // try something here + print $e; +} \ No newline at end of file diff --git a/vendor/jpush/jpush/phpunit.xml.dist b/vendor/jpush/jpush/phpunit.xml.dist new file mode 100644 index 00000000..2b8af6ee --- /dev/null +++ b/vendor/jpush/jpush/phpunit.xml.dist @@ -0,0 +1,15 @@ + + + + + tests/JPush + + + diff --git a/vendor/jpush/jpush/src/JPush/AdminClient.php b/vendor/jpush/jpush/src/JPush/AdminClient.php new file mode 100644 index 00000000..cfe96fd7 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/AdminClient.php @@ -0,0 +1,42 @@ +devKey = $devKey; + $this->devSecret = $devSecret; + $this->retryTimes = 1; + $this->logFile = null; + } + + public function getAuthStr() { return $this->devKey . ":" . $this->devSecret; } + public function getRetryTimes() { return $this->retryTimes; } + public function getLogFile() { return $this->logFile; } + + public function createApp($appName, $androidPackage, $groupName=null) { + $url = AdminClient::ADMIN_URL; + $body = [ + 'app_name' => $appName, + 'android_package'=> $androidPackage, + 'group_name' => $groupName + + ]; + return Http::post($this, $url, $body); + } + + public function deleteApp($appKey) { + $url = AdminClient::ADMIN_URL . $appKey . '/delete'; + return Http::post($this, $url, []); + } +} diff --git a/vendor/jpush/jpush/src/JPush/Client.php b/vendor/jpush/jpush/src/JPush/Client.php new file mode 100644 index 00000000..9c07d00c --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Client.php @@ -0,0 +1,71 @@ + [ + 'push' => 'https://api.jpush.cn/v3/', + 'report' => 'https://report.jpush.cn/v3/', + 'device' => 'https://device.jpush.cn/v3/devices/', + 'alias' => 'https://device.jpush.cn/v3/aliases/', + 'tag' => 'https://device.jpush.cn/v3/tags/', + 'schedule' => 'https://api.jpush.cn/v3/schedules' + ], + 'BJ' => [ + 'push' => 'https://bjapi.push.jiguang.cn/v3/', + 'report' => 'https://bjapi.push.jiguang.cn/v3/report/', + 'device' => 'https://bjapi.push.jiguang.cn/v3/device/', + 'alias' => 'https://bjapi.push.jiguang.cn/v3/device/aliases/', + 'tag' => 'https://bjapi.push.jiguang.cn/v3/device/tags/', + 'schedules' => 'https://bjapi.push.jiguang.cn/v3/push/schedules' + ] + ]; + + public function __construct($appKey, $masterSecret, $logFile=Config::DEFAULT_LOG_FILE, $retryTimes=Config::DEFAULT_MAX_RETRY_TIMES, $zone = null) { + if (!is_string($appKey) || !is_string($masterSecret)) { + throw new InvalidArgumentException("Invalid appKey or masterSecret"); + } + $this->appKey = $appKey; + $this->masterSecret = $masterSecret; + if (!is_null($retryTimes)) { + $this->retryTimes = $retryTimes; + } else { + $this->retryTimes = 1; + } + $this->logFile = $logFile; + if (!is_null($zone) && in_array(strtoupper($zone), array_keys(self::$zones))) { + $this->zone = strtoupper($zone); + } else { + $this->zone = null; + } + } + + public function push() { return new PushPayload($this); } + public function report() { return new ReportPayload($this); } + public function device() { return new DevicePayload($this); } + public function schedule() { return new SchedulePayload($this);} + + public function getAuthStr() { return $this->appKey . ":" . $this->masterSecret; } + public function getRetryTimes() { return $this->retryTimes; } + public function getLogFile() { return $this->logFile; } + + public function is_group() { + $str = substr($this->appKey, 0, 6); + return $str === 'group-'; + } + + public function makeURL($key) { + if (is_null($this->zone)) { + return self::$zones['DEFAULT'][$key]; + } else { + return self::$zones[$this->zone][$key]; + } + } +} diff --git a/vendor/jpush/jpush/src/JPush/Config.php b/vendor/jpush/jpush/src/JPush/Config.php new file mode 100644 index 00000000..e2007a10 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Config.php @@ -0,0 +1,16 @@ +client = $client; + } + + public function getDevices($registrationId) { + $url = $this->client->makeURL('device') . $registrationId; + return Http::get($this->client, $url); + } + + public function updateAlias($registration_id, $alias) { + return $this->updateDevice($registration_id, $alias); + } + public function addTags($registration_id, $tags) { + $tags = is_array($tags) ? $tags : array($tags); + return $this->updateDevice($registration_id, null, null, $tags); + } + public function removeTags($registration_id, $tags) { + $tags = is_array($tags) ? $tags : array($tags); + return $this->updateDevice($registration_id, null, null, null, $tags); + } + public function updateMoblie($registration_id, $mobile) { + return $this->updateDevice($registration_id, null, $mobile); + } + + public function clearMobile($registrationId) { + $url = $this->client->makeURL('device') . $registrationId; + return Http::post($this->client, $url, ['mobile' => '']); + } + + public function clearTags($registrationId) { + $url = $this->client->makeURL('device') . $registrationId; + return Http::post($this->client, $url, ['tags' => '']); + } + + public function updateDevice($registrationId, $alias = null, $mobile = null, $addTags = null, $removeTags = null) { + $payload = array(); + if (!is_string($registrationId)) { + throw new InvalidArgumentException('Invalid registration_id'); + } + + $aliasIsNull = is_null($alias); + $mobileIsNull = is_null($mobile); + $addTagsIsNull = is_null($addTags); + $removeTagsIsNull = is_null($removeTags); + + if ($aliasIsNull && $addTagsIsNull && $removeTagsIsNull && $mobileIsNull) { + throw new InvalidArgumentException("alias, addTags, removeTags not all null"); + } + + if (!$aliasIsNull) { + if (is_string($alias)) { + $payload['alias'] = $alias; + } else { + throw new InvalidArgumentException("Invalid alias string"); + } + } + + if (!$mobileIsNull) { + if (is_string($mobile)) { + $payload['mobile'] = $mobile; + } else { + throw new InvalidArgumentException("Invalid mobile string"); + } + } + + $tags = array(); + + if (!$addTagsIsNull) { + if (is_array($addTags)) { + $tags['add'] = $addTags; + } else { + throw new InvalidArgumentException("Invalid addTags array"); + } + } + + if (!$removeTagsIsNull) { + if (is_array($removeTags)) { + $tags['remove'] = $removeTags; + } else { + throw new InvalidArgumentException("Invalid removeTags array"); + } + } + + if (count($tags) > 0) { + $payload['tags'] = $tags; + } + + $url = $this->client->makeURL('device') . $registrationId; + return Http::post($this->client, $url, $payload); + } + + public function getTags() { + $url = $this->client->makeURL('tag'); + return Http::get($this->client, $url); + } + + public function isDeviceInTag($registrationId, $tag) { + if (!is_string($registrationId)) { + throw new InvalidArgumentException("Invalid registration_id"); + } + + if (!is_string($tag)) { + throw new InvalidArgumentException("Invalid tag"); + } + $url = $this->client->makeURL('tag') . $tag . '/registration_ids/' . $registrationId; + return Http::get($this->client, $url); + } + + public function addDevicesToTag($tag, $addDevices) { + $device = is_array($addDevices) ? $addDevices : array($addDevices); + return $this->updateTag($tag, $device, null); + } + public function removeDevicesFromTag($tag, $removeDevices) { + $device = is_array($removeDevices) ? $removeDevices : array($removeDevices); + return $this->updateTag($tag, null, $device); + } + public function updateTag($tag, $addDevices = null, $removeDevices = null) { + if (!is_string($tag)) { + throw new InvalidArgumentException("Invalid tag"); + } + + $addDevicesIsNull = is_null($addDevices); + $removeDevicesIsNull = is_null($removeDevices); + + if ($addDevicesIsNull && $removeDevicesIsNull) { + throw new InvalidArgumentException("Either or both addDevices and removeDevices must be set."); + } + + $registrationId = array(); + + if (!$addDevicesIsNull) { + if (is_array($addDevices)) { + $registrationId['add'] = $addDevices; + } else { + throw new InvalidArgumentException("Invalid addDevices"); + } + } + + if (!$removeDevicesIsNull) { + if (is_array($removeDevices)) { + $registrationId['remove'] = $removeDevices; + } else { + throw new InvalidArgumentException("Invalid removeDevices"); + } + } + + $url = $this->client->makeURL('tag') . $tag; + $payload = array('registration_ids'=>$registrationId); + return Http::post($this->client, $url, $payload); + } + + public function deleteTag($tag) { + if (!is_string($tag)) { + throw new InvalidArgumentException("Invalid tag"); + } + $url = $this->client->makeURL('tag') . $tag; + return Http::delete($this->client, $url); + } + + public function getAliasDevices($alias, $platform = null) { + if (!is_string($alias)) { + throw new InvalidArgumentException("Invalid alias"); + } + + $url = $this->client->makeURL('alias') . $alias; + + if (!is_null($platform)) { + if (is_array($platform)) { + $isFirst = true; + foreach($platform as $item) { + if ($isFirst) { + $url = $url . '?platform=' . $item; + $isFirst = false; + } else { + $url = $url . ',' . $item; + } + } + } else if (is_string($platform)) { + $url = $url . '?platform=' . $platform; + } else { + throw new InvalidArgumentException("Invalid platform"); + } + } + return Http::get($this->client, $url); + } + + public function deleteAlias($alias) { + if (!is_string($alias)) { + throw new InvalidArgumentException("Invalid alias"); + } + $url = $this->client->makeURL('alias') . $alias; + return Http::delete($this->client, $url); + } + + public function getDevicesStatus($registrationId) { + if (!is_array($registrationId) && !is_string($registrationId)) { + throw new InvalidArgumentException('Invalid registration_id'); + } + + if (is_string($registrationId)) { + $registrationId = explode(',', $registrationId); + } + + $payload = array(); + if (count($registrationId) <= 0) { + throw new InvalidArgumentException('Invalid registration_id'); + } + $payload['registration_ids'] = $registrationId; + $url = $this->client->makeURL('device') . 'status'; + return Http::post($this->client, $url, $payload); + } +} diff --git a/vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php b/vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php new file mode 100644 index 00000000..e5dcb936 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Exceptions/APIConnectionException.php @@ -0,0 +1,9 @@ +message} \n"; + } +} diff --git a/vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php b/vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php new file mode 100644 index 00000000..dc98b788 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Exceptions/APIRequestException.php @@ -0,0 +1,36 @@ +http_code = $response['http_code']; + $this->headers = $response['headers']; + + $body = json_decode($response['body'], true); + + if (key_exists('error', $body)) { + $this->code = $body['error']['code']; + $this->message = $body['error']['message']; + } else { + $this->code = $body['code']; + $this->message = $body['message']; + } + } + + public function __toString() { + return "\n" . __CLASS__ . " -- [{$this->code}]: {$this->message} \n"; + } + + public function getHttpCode() { + return $this->http_code; + } + public function getHeaders() { + return $this->headers; + } + +} diff --git a/vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php b/vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php new file mode 100644 index 00000000..e59460a7 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Exceptions/JPushException.php @@ -0,0 +1,9 @@ +http_code = $response['http_code']; + $this->headers = $response['headers']; + $this->message = $response['body']; + } + + function __toString() { + return "\n" . __CLASS__ . " -- [{$this->http_code}]: {$this->message} \n"; + } + + public function getHttpCode() { + return $this->http_code; + } + public function getHeaders() { + return $this->headers; + } +} diff --git a/vendor/jpush/jpush/src/JPush/Http.php b/vendor/jpush/jpush/src/JPush/Http.php new file mode 100644 index 00000000..20fe8bd0 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/Http.php @@ -0,0 +1,139 @@ +getAuthStr()); + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + + // 设置Post参数 + if ($method === Config::HTTP_POST) { + curl_setopt($ch, CURLOPT_POST, true); + } else if ($method === Config::HTTP_DELETE || $method === Config::HTTP_PUT) { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + } + if (!is_null($body)) { + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body)); + } + + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Connection: Keep-Alive' + )); + + $output = curl_exec($ch); + $response = array(); + $errorCode = curl_errno($ch); + + // $msg = ''; + // $data = json_decode($body, true); + // if (isset($data['options']['sendno'])) { + // $sendno = $data['options']['sendno']; + // $msg = 'sendno: ' . $sendno; + // } + + $msg = ''; + if (isset($body['options']['sendno'])) { + $sendno = $body['options']['sendno']; + $msg = 'sendno: ' . $sendno; + } + + + if ($errorCode) { + $retries = $client->getRetryTimes(); + if ($times < $retries) { + return self::sendRequest($client, $url, $method, $body, ++$times); + } else { + if ($errorCode === 28) { + throw new APIConnectionException($msg . "Response timeout. Your request has probably be received by JPush Server,please check that whether need to be pushed again." ); + } elseif ($errorCode === 56) { + // resolve error[56 Problem (2) in the Chunked-Encoded data] + throw new APIConnectionException($msg . "Response timeout, maybe cause by old CURL version. Your request has probably be received by JPush Server, please check that whether need to be pushed again."); + } else { + throw new APIConnectionException("$msg . Connect timeout. Please retry later. Error:" . $errorCode . " " . curl_error($ch)); + } + } + } else { + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header_text = substr($output, 0, $header_size); + $body = substr($output, $header_size); + $headers = array(); + foreach (explode("\r\n", $header_text) as $i => $line) { + if (!empty($line)) { + if ($i === 0) { + $headers[0] = $line; + } else if (strpos($line, ": ")) { + list ($key, $value) = explode(': ', $line); + $headers[$key] = $value; + } + } + } + $response['headers'] = $headers; + $response['body'] = $body; + $response['http_code'] = $httpCode; + } + curl_close($ch); + return $response; + } + + public static function processResp($response) { + $data = json_decode($response['body'], true); + if ($response['http_code'] === 200) { + $result = array(); + $result['body'] = $data; + $result['http_code'] = $response['http_code']; + $result['headers'] = $response['headers']; + return $result; + } elseif (is_null($data)) { + throw new ServiceNotAvaliable($response); + } else { + throw new APIRequestException($response); + } + } + + public static function log($client, $content) { + if (!is_null($client->getLogFile())) { + error_log($content . "\r\n", 3, $client->getLogFile()); + } + } +} diff --git a/vendor/jpush/jpush/src/JPush/PushPayload.php b/vendor/jpush/jpush/src/JPush/PushPayload.php new file mode 100644 index 00000000..6a1d23ab --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/PushPayload.php @@ -0,0 +1,761 @@ +client = $client; + $url = $this->client->is_group() ? 'grouppush' : 'push'; + $this->url = $this->client->makeURL('push') . $url; + } + + public function getCid($count = 1, $type = 'push') { + $url = $this->client->makeURL('push') . 'push/cid?count=' . $count . '&type=' . $type; + return Http::get($this->client, $url); + } + + public function setCid($cid) { + $this->cid = trim($cid); + return $this; + } + + public function setPlatform($platform) { + # $required_keys = array('all', 'android', 'ios', 'winphone'); + if (is_string($platform)) { + $ptf = strtolower($platform); + if ('all' === $ptf) { + $this->platform = 'all'; + } elseif (in_array($ptf, self::$EFFECTIVE_DEVICE_TYPES)) { + $this->platform = array($ptf); + } + } elseif (is_array($platform)) { + $ptf = array_map('strtolower', $platform); + $this->platform = array_intersect($ptf, self::$EFFECTIVE_DEVICE_TYPES); + } + return $this; + } + + public function setAudience($all) { + if (strtolower($all) === 'all') { + $this->addAllAudience(); + return $this; + } else { + throw new InvalidArgumentException('Invalid audience value'); + } + } + + public function addAllAudience() { + $this->audience = "all"; + return $this; + } + + public function addTag($tag) { + return $this->updateAudience('tags', $tag, 'tag'); + } + + public function addTagAnd($tag) { + return $this->updateAudience('tagAnds', $tag, 'tag_and'); + } + + public function addTagNot($tag) { + return $this->updateAudience('tagNots', $tag, 'tag_not'); + } + + public function addAlias($alias) { + return $this->updateAudience('alias', $alias, 'alias'); + } + + public function addRegistrationId($registrationId) { + return $this->updateAudience('registrationIds', $registrationId, 'registration_id'); + } + + public function addSegmentId($segmentId) { + return $this->updateAudience('segmentIds', $segmentId, 'segment'); + } + + public function addAbtest($abtest) { + return $this->updateAudience('abtests', $abtest, 'abtest'); + } + + private function updateAudience($key, $value, $name) { + if (is_null($this->$key)) { + $this->$key = array(); + } + + if (is_array($value)) { + foreach($value as $v) { + if (!is_string($v)) { + throw new InvalidArgumentException("Invalid $name value"); + } + if (!in_array($v, $this->$key)) { + array_push($this->$key, $v); + } + } + } else if (is_string($value)) { + if (!in_array($value, $this->$key)) { + array_push($this->$key, $value); + } + } else { + throw new InvalidArgumentException("Invalid $name value"); + } + + return $this; + } + + public function setNotificationAlert($alert) { + if (!is_string($alert)) { + throw new InvalidArgumentException("Invalid alert value"); + } + $this->notificationAlert = $alert; + return $this; + } + + public function addWinPhoneNotification($alert=null, $title=null, $_open_page=null, $extras=null) { + $winPhone = array(); + + if (!is_null($alert)) { + if (!is_string($alert)) { + throw new InvalidArgumentException("Invalid winphone notification"); + } + $winPhone['alert'] = $alert; + } + + if (!is_null($title)) { + if (!is_string($title)) { + throw new InvalidArgumentException("Invalid winphone title notification"); + } + if(strlen($title) > 0) { + $winPhone['title'] = $title; + } + } + + if (!is_null($_open_page)) { + if (!is_string($_open_page)) { + throw new InvalidArgumentException("Invalid winphone _open_page notification"); + } + if (strlen($_open_page) > 0) { + $winPhone['_open_page'] = $_open_page; + } + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid winphone extras notification"); + } + if (count($extras) > 0) { + $winPhone['extras'] = $extras; + } + } + + if (count($winPhone) <= 0) { + throw new InvalidArgumentException("Invalid winphone notification"); + } + + $this->winPhoneNotification = $winPhone; + return $this; + } + + public function setSms($delay_time, $temp_id, array $temp_para = []) { + $sms = array(); + $sms['temp_id'] = $temp_id; + $sms['delay_time'] = ($delay_time === 0 || (is_int($delay_time) && $delay_time > 0 && $delay_time <= 86400)) ? $delay_time : 0; + + if (!empty($temp_para)) { + $sms['temp_para'] = $temp_para; + } + + $this->smsMessage = $sms; + return $this; + } + + public function build() { + $payload = array(); + + // validate platform + if (is_null($this->platform)) { + throw new InvalidArgumentException("platform must be set"); + } + $payload["platform"] = $this->platform; + + if (!is_null($this->cid)) { + $payload['cid'] = $this->cid; + } + + // validate audience + $audience = array(); + if (!is_null($this->tags)) { + $audience["tag"] = $this->tags; + } + if (!is_null($this->tagAnds)) { + $audience["tag_and"] = $this->tagAnds; + } + if (!is_null($this->tagNots)) { + $audience["tag_not"] = $this->tagNots; + } + if (!is_null($this->alias)) { + $audience["alias"] = $this->alias; + } + if (!is_null($this->registrationIds)) { + $audience["registration_id"] = $this->registrationIds; + } + if (!is_null($this->segmentIds)) { + $audience["segment"] = $this->segmentIds; + } + if (!is_null($this->abtests)) { + $audience["abtest"] = $this->abtests; + } + if (is_null($this->audience) && count($audience) <= 0) { + throw new InvalidArgumentException("audience must be set"); + } else if (!is_null($this->audience) && count($audience) > 0) { + throw new InvalidArgumentException("you can't add tags/alias/registration_id/tag_and when audience='all'"); + } else if (is_null($this->audience)) { + $payload["audience"] = $audience; + } else { + $payload["audience"] = $this->audience; + } + + + // validate notification + $notification = array(); + + if (!is_null($this->notificationAlert)) { + $notification['alert'] = $this->notificationAlert; + } + + if (!is_null($this->androidNotification)) { + $notification['android'] = $this->androidNotification; + if (is_null($this->androidNotification['alert'])) { + if (is_null($this->notificationAlert)) { + throw new InvalidArgumentException("Android alert can not be null"); + } else { + $notification['android']['alert'] = $this->notificationAlert; + } + } + } + + if (!is_null($this->iosNotification)) { + $notification['ios'] = $this->iosNotification; + if (is_null($this->iosNotification['alert'])) { + if (is_null($this->notificationAlert)) { + throw new InvalidArgumentException("iOS alert can not be null"); + } else { + $notification['ios']['alert'] = $this->notificationAlert; + } + } + } + + if (!is_null($this->winPhoneNotification)) { + $notification['winphone'] = $this->winPhoneNotification; + if (is_null($this->winPhoneNotification['alert'])) { + if (is_null($this->winPhoneNotification)) { + throw new InvalidArgumentException("WinPhone alert can not be null"); + } else { + $notification['winphone']['alert'] = $this->notificationAlert; + } + } + } + + if (!is_null($this->voip)) { + $notification['voip'] = $this->voip; + } + + if (count($notification) > 0) { + $payload['notification'] = $notification; + } + + if (!is_null($this->message)) { + $payload['message'] = $this->message; + } + if (!array_key_exists('notification', $payload) && !array_key_exists('message', $payload)) { + throw new InvalidArgumentException('notification and message can not all be null'); + } + + if (!is_null($this->smsMessage)) { + $payload['sms_message'] = $this->smsMessage; + } + + if (is_null($this->options)) { + $this->options(); + } + + $payload['options'] = $this->options; + + if (!is_null($this->custom)) { + foreach($this->custom as $key=>$val) { + $payload[$key] = $val; + } + } + + return $payload; + } + + public function toJSON() { + $payload = $this->build(); + return json_encode($payload); + } + + public function printJSON() { + echo $this->toJSON(); + return $this; + } + + public function send() { + return Http::post($this->client, $this->url, $this->build()); + } + + public function validate() { + $url = $this->client->makeURL('push') . '/push/validate'; + return Http::post($this->client, $url, $this->build()); + } + + private function generateSendno() { + return rand(100000, getrandmax()); + } + + # new methods + public function iosNotification($alert = '', array $notification = array()) { + $ios = array(); + $ios['alert'] = (is_string($alert) || is_array($alert)) ? $alert : ''; + if (!empty($notification)) { + if (isset($notification['sound'])) { + if (is_string($notification['sound']) || is_array($notification['sound'])) { + $ios['sound'] = $notification['sound']; + } else { + unset($notification['sound']); + } + } + if (isset($notification['content-available'])) { + if (is_bool($notification['content-available'])) { + $ios['content-available'] = $notification['content-available']; + } else { + unset($notification['content-available']); + } + } + if (isset($notification['mutable-content'])) { + if (is_bool($notification['mutable-content'])) { + $ios['mutable-content'] = $notification['mutable-content']; + } else { + unset($notification['mutable-content']); + } + } + if (isset($notification['extras'])) { + if (is_array($notification['extras']) && !empty($notification['extras'])) { + $ios['extras'] = $notification['extras']; + } else { + unset($notification['extras']); + } + } + $ios = array_merge($notification, $ios); + } + if (!isset($ios['sound'])) { + $ios['sound'] = ''; + } + if (!isset($ios['badge'])) { + $ios['badge'] = '+1'; + } + $this->iosNotification = $ios; + return $this; + } + + public function androidNotification($alert = '', array $notification = array()) { + $android = array(); + $android['alert'] = is_string($alert) ? $alert : ''; + if (!empty($notification)) { + if (isset($notification['builder_id'])) { + if (is_int($notification['builder_id'])) { + $android['builder_id'] = $notification['builder_id']; + } else { + unset($notification['builder_id']); + } + } + if (isset($notification['priority'])) { + if (is_int($notification['priority'])) { + $android['priority'] = $notification['priority']; + } else { + unset($notification['priority']); + } + } + if (isset($notification['style'])) { + if (is_int($notification['style'])) { + $android['style'] = $notification['style']; + } else { + unset($notification['style']); + } + } + if (isset($notification['alert_type'])) { + if (is_int($notification['alert_type'])) { + $android['alert_type'] = $notification['alert_type']; + } else { + unset($notification['alert_type']); + } + } + if (isset($notification['inbox'])) { + if (is_array($notification['inbox']) && !empty($notification['inbox'])) { + $android['inbox'] = $notification['inbox']; + } else { + unset($notification['inbox']); + } + } + if (isset($notification['intent'])) { + if (is_array($notification['intent']) && !empty($notification['intent'])) { + $android['intent'] = $notification['intent']; + } else { + unset($notification['intent']); + } + } + if (isset($notification['extras'])) { + if (is_array($notification['extras']) && !empty($notification['extras'])) { + $android['extras'] = $notification['extras']; + } else { + unset($notification['extras']); + } + } + $android = array_merge($notification, $android); + } + $this->androidNotification = $android; + return $this; + } + + /** + * Voip in notification + * could add any custom key/value into it + */ + public function voip (array $extras = array()) { + $voip = array(); + if(!empty($extras)) { + foreach($extras as $key=>$val) { + $voip[$key] = $val; + } + } + $voip = array_merge($extras, $voip); + $this->voip=$voip; + return $this; + } + + public function message($msg_content, array $msg = array()) { + # $required_keys = array('title', 'content_type', 'extras'); + if (is_string($msg_content)) { + $message = array(); + $message['msg_content'] = $msg_content; + if (!empty($msg)) { + if (isset($msg['title']) && is_string($msg['title'])) { + $message['title'] = $msg['title']; + } + if (isset($msg['content_type']) && is_string($msg['content_type'])) { + $message['content_type'] = $msg['content_type']; + } + if (isset($msg['extras']) && is_array($msg['extras']) && !empty($msg['extras'])) { + $message['extras'] = $msg['extras']; + } + } + $this->message = $message; + } + return $this; + } + + public function options(array $opts = array()) { + # $required_keys = array('sendno', 'time_to_live', 'override_msg_id', 'apns_production', 'apns_collapse_id', 'big_push_duration'); + $options = array(); + if (isset($opts['sendno'])) { + $options['sendno'] = $opts['sendno']; + } else { + $options['sendno'] = $this->generateSendno(); + } + if (isset($opts['time_to_live']) && $opts['time_to_live'] <= 864000 && $opts['time_to_live'] >= 0) { + $options['time_to_live'] = $opts['time_to_live']; + } + if (isset($opts['override_msg_id'])) { + $options['override_msg_id'] = $opts['override_msg_id']; + } + if (isset($opts['apns_production'])) { + $options['apns_production'] = (bool)$opts['apns_production']; + } else { + $options['apns_production'] = false; + } + if (isset($opts['apns_collapse_id'])) { + $options['apns_collapse_id'] = $opts['apns_collapse_id']; + } + if (isset($opts['big_push_duration']) && $opts['big_push_duration'] <= 1400 && $opts['big_push_duration'] >= 0) { + $options['big_push_duration'] = $opts['big_push_duration']; + } + $options = array_merge($opts, $options); + $this->options = $options; + + return $this; + } + + public function custom (array $extras = array()) { + if(!empty($extras)) { + $this->custom=$extras; + } + return $this; + } + + ############################################################################### + ############# 以下函数已过期,不推荐使用,仅作为兼容接口存在 ######################### + ############################################################################### + public function addIosNotification($alert=null, $sound=null, $badge=null, $content_available=null, $category=null, $extras=null) { + $ios = array(); + + if (!is_null($alert)) { + if (!is_string($alert) && !is_array($alert)) { + throw new InvalidArgumentException("Invalid ios alert value"); + } + $ios['alert'] = $alert; + } + + if (!is_null($sound)) { + if (!is_string($sound)) { + throw new InvalidArgumentException("Invalid ios sound value"); + } + if ($sound !== Config::DISABLE_SOUND) { + $ios['sound'] = $sound; + } + } else { + // 默认sound为'' + $ios['sound'] = ''; + } + + if (!is_null($badge)) { + if (is_string($badge) && !preg_match("/^[+-]{1}[0-9]{1,3}$/", $badge)) { + if (!is_int($badge)) { + throw new InvalidArgumentException("Invalid ios badge value"); + } + } + if ($badge != Config::DISABLE_BADGE) { + $ios['badge'] = $badge; + } + } else { + // 默认badge为'+1' + $ios['badge'] = '+1'; + } + + if (!is_null($content_available)) { + if (!is_bool($content_available)) { + throw new InvalidArgumentException("Invalid ios content-available value"); + } + $ios['content-available'] = $content_available; + } + + if (!is_null($category)) { + if (!is_string($category)) { + throw new InvalidArgumentException("Invalid ios category value"); + } + if (strlen($category)) { + $ios['category'] = $category; + } + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid ios extras value"); + } + if (count($extras) > 0) { + $ios['extras'] = $extras; + } + } + + if (count($ios) <= 0) { + throw new InvalidArgumentException("Invalid iOS notification"); + } + + $this->iosNotification = $ios; + return $this; + } + + public function addAndroidNotification($alert=null, $title=null, $builderId=null, $extras=null) { + $android = array(); + + if (!is_null($alert)) { + if (!is_string($alert)) { + throw new InvalidArgumentException("Invalid android alert value"); + } + $android['alert'] = $alert; + } + + if (!is_null($title)) { + if(!is_string($title)) { + throw new InvalidArgumentException("Invalid android title value"); + } + if(strlen($title) > 0) { + $android['title'] = $title; + } + } + + if (!is_null($builderId)) { + if (!is_int($builderId)) { + throw new InvalidArgumentException("Invalid android builder_id value"); + } + $android['builder_id'] = $builderId; + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid android extras value"); + } + if (count($extras) > 0) { + $android['extras'] = $extras; + } + } + + if (count($android) <= 0) { + throw new InvalidArgumentException("Invalid android notification"); + } + + $this->androidNotification = $android; + return $this; + } + + public function setMessage($msg_content, $title=null, $content_type=null, $extras=null) { + $message = array(); + + if (is_null($msg_content) || !is_string($msg_content)) { + throw new InvalidArgumentException("Invalid message content"); + } else { + $message['msg_content'] = $msg_content; + } + + if (!is_null($title)) { + if (!is_string($title)) { + throw new InvalidArgumentException("Invalid message title"); + } + $message['title'] = $title; + } + + if (!is_null($content_type)) { + if (!is_string($content_type)) { + throw new InvalidArgumentException("Invalid message content type"); + } + $message["content_type"] = $content_type; + } + + if (!is_null($extras)) { + if (!is_array($extras)) { + throw new InvalidArgumentException("Invalid message extras"); + } + if (count($extras) > 0) { + $message['extras'] = $extras; + } + } + + $this->message = $message; + return $this; + } + + public function setSmsMessage($smsMessage) { + $this->smsMessage = $smsMessage; + return $this; + } + + public function setOptions($sendno=null, $time_to_live=null, $override_msg_id=null, $apns_production=null, $big_push_duration=null) { + $options = array(); + + if (!is_null($sendno)) { + if (!is_int($sendno)) { + throw new InvalidArgumentException('Invalid option sendno'); + } + $options['sendno'] = $sendno; + } else { + $options['sendno'] = $this->generateSendno(); + } + + if (!is_null($time_to_live)) { + if (!is_int($time_to_live) || $time_to_live < 0 || $time_to_live > 864000) { + throw new InvalidArgumentException('Invalid option time to live, it must be a int and in [0, 864000]'); + } + $options['time_to_live'] = $time_to_live; + } + + if (!is_null($override_msg_id)) { + if (!is_long($override_msg_id)) { + throw new InvalidArgumentException('Invalid option override msg id'); + } + $options['override_msg_id'] = $override_msg_id; + } + + if (!is_null($apns_production)) { + if (!is_bool($apns_production)) { + throw new InvalidArgumentException('Invalid option apns production'); + } + $options['apns_production'] = $apns_production; + } else { + $options['apns_production'] = false; + } + + if (!is_null($big_push_duration)) { + if (!is_int($big_push_duration) || $big_push_duration < 0 || $big_push_duration > 1440) { + throw new InvalidArgumentException('Invalid option big push duration, it must be a int and in [0, 1440]'); + } + $options['big_push_duration'] = $big_push_duration; + } + + $this->options = $options; + return $this; + } + + /* + 针对RegID方式批量单推 + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#vip + */ + public function batchPushByRegid(array $singlePayloads) { + $body = array( + "pushlist"=>array() + ); + $response = $this -> getCid(count($singlePayloads), 'push'); + $cidlist = $response['body']['cidlist']; + foreach ($cidlist as $i => $cid) { + $body["pushlist"][$cid] = $singlePayloads[$i]; + } + $url = $this->client->makeURL('push') . 'push/batch/regid/single'; + return Http::post($this->client, $url, $body); + } + + /* + 针对Alias方式批量单推 + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push/#vip + */ + public function batchPushByAlias(array $singlePayloads) { + $body = array( + "pushlist"=>array() + ); + $response = $this -> getCid(count($singlePayloads), 'push'); + $cidlist = $response['body']['cidlist']; + foreach ($cidlist as $i => $cid) { + $body["pushlist"][$cid] = $singlePayloads[$i]; + } + $url = $this->client->makeURL('push') . 'push/batch/alias/single'; + return Http::post($this->client, $url, $body); + } +} diff --git a/vendor/jpush/jpush/src/JPush/ReportPayload.php b/vendor/jpush/jpush/src/JPush/ReportPayload.php new file mode 100644 index 00000000..520137d1 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/ReportPayload.php @@ -0,0 +1,109 @@ +client = $client; + } + + public function getReceived($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'received' . $queryParams; + return Http::get($this->client, $url); + } + + /* + 送达统计详情(新) + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_report/#_7 + */ + public function getReceivedDetail($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'received/detail' . $queryParams; + return Http::get($this->client, $url); + } + + public function getMessageStatus($msgId, $rids, $data = null) { + $url = $this->client->makeURL('report') . 'status/message'; + $registrationIds = is_array($rids) ? $rids : array($rids); + $body = [ + 'msg_id' => $msgId, + 'registration_ids' => $registrationIds + ]; + if (!is_null($data)) { + $body['data'] = $data; + } + return Http::post($this->client, $url, $body); + } + + public function getMessages($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'messages/' .$queryParams; + return Http::get($this->client, $url); + } + + /* + 消息统计详情(VIP 专属接口,新) + https://docs.jiguang.cn/jpush/server/push/rest_api_v3_report/#vip_1 + */ + public function getMessagesDetail($msgIds) { + $queryParams = '?msg_ids='; + if (is_array($msgIds) && !empty($msgIds)) { + $msgIdsStr = implode(',', $msgIds); + $queryParams .= $msgIdsStr; + } elseif (is_string($msgIds)) { + $queryParams .= $msgIds; + } else { + throw new InvalidArgumentException("Invalid msg_ids"); + } + + $url = $this->client->makeURL('report') . 'messages/detail' .$queryParams; + return Http::get($this->client, $url); + } + + public function getUsers($time_unit, $start, $duration) { + $time_unit = strtoupper($time_unit); + if (!in_array($time_unit, self::$EFFECTIVE_TIME_UNIT)) { + throw new InvalidArgumentException('Invalid time unit'); + } + + $url = $this->client->makeURL('report') . 'users/?time_unit=' . $time_unit . '&start=' . $start . '&duration=' . $duration; + return Http::get($this->client, $url); + } +} diff --git a/vendor/jpush/jpush/src/JPush/SchedulePayload.php b/vendor/jpush/jpush/src/JPush/SchedulePayload.php new file mode 100644 index 00000000..5f35262e --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/SchedulePayload.php @@ -0,0 +1,182 @@ +client = $client; + } + + public function createSingleSchedule($name, $push_payload, $trigger) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } + $payload = array(); + $payload['name'] = $name; + $payload['enabled'] = true; + $payload['trigger'] = array("single"=>$trigger); + $payload['push'] = $push_payload; + + $url = $this->client->makeURL('schedule'); + return Http::post($this->client, $url, $payload); + } + + public function createPeriodicalSchedule($name, $push_payload, $trigger) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } + $payload = array(); + $payload['name'] = $name; + $payload['enabled'] = true; + $payload['trigger'] = array("periodical"=>$trigger); + $payload['push'] = $push_payload; + + $url = $this->client->makeURL('schedule'); + return Http::post($this->client, $url, $payload); + } + + public function updateSingleSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $payload = array(); + if (!is_null($name)) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } else { + $payload['name'] = $name; + } + } + + if (!is_null($enabled)) { + if (!is_bool($enabled)) { + throw new InvalidArgumentException('Invalid schedule enable'); + } else { + $payload['enabled'] = $enabled; + } + } + + if (!is_null($push_payload)) { + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } else { + $payload['push'] = $push_payload; + } + } + + if (!is_null($trigger)) { + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } else { + $payload['trigger'] = array("single"=>$trigger); + } + } + + if (count($payload) <= 0) { + throw new InvalidArgumentException('Invalid schedule, name, enabled, trigger, push can not all be null'); + } + + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + + return Http::put($this->client, $url, $payload); + + } + + public function updatePeriodicalSchedule($schedule_id, $name=null, $enabled=null, $push_payload=null, $trigger=null) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $payload = array(); + if (!is_null($name)) { + if (!is_string($name)) { + throw new InvalidArgumentException('Invalid schedule name'); + } else { + $payload['name'] = $name; + } + } + + if (!is_null($enabled)) { + if (!is_bool($enabled)) { + throw new InvalidArgumentException('Invalid schedule enable'); + } else { + $payload['enabled'] = $enabled; + } + } + + if (!is_null($push_payload)) { + if (!is_array($push_payload)) { + throw new InvalidArgumentException('Invalid schedule push payload'); + } else { + $payload['push'] = $push_payload; + } + } + + if (!is_null($trigger)) { + if (!is_array($trigger)) { + throw new InvalidArgumentException('Invalid schedule trigger'); + } else { + $payload['trigger'] = array("periodical"=>$trigger); + } + } + + if (count($payload) <= 0) { + throw new InvalidArgumentException('Invalid schedule, name, enabled, trigger, push can not all be null'); + } + + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + return Http::put($this->client, $url, $payload); + } + + public function getSchedules($page = 1) { + if (!is_int($page)) { + $page = 1; + } + $url = $this->client->makeURL('schedule') . "?page=" . $page; + return Http::get($this->client, $url); + } + + public function getSchedule($schedule_id) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + return Http::get($this->client, $url); + } + + public function deleteSchedule($schedule_id) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $url = $this->client->makeURL('schedule') . "/" . $schedule_id; + return Http::delete($this->client, $url); + } + + public function getMsgIds($schedule_id) { + if (!is_string($schedule_id)) { + throw new InvalidArgumentException('Invalid schedule id'); + } + $url = $this->client->makeURL('schedule') . '/' . $schedule_id . '/msg_ids'; + return Http::get($this->client, $url); + } + +} + diff --git a/vendor/jpush/jpush/src/JPush/version.php b/vendor/jpush/jpush/src/JPush/version.php new file mode 100644 index 00000000..31f70473 --- /dev/null +++ b/vendor/jpush/jpush/src/JPush/version.php @@ -0,0 +1,4 @@ +device = $client->device(); + $this->test_tag = 'jpush_tag'; + } + + function testGetDevices() { + global $registration_id; + $response = $this->device->getDevices($registration_id); + $this->assertEquals('200', $response['http_code']); + + echo "HTTP HEADERS ARE: "; + print_r($response['headers']); + + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(3, count($body)); + $this->assertArrayHasKey('tags', $body); + $this->assertArrayHasKey('alias', $body); + $this->assertArrayHasKey('mobile', $body); + $this->assertTrue(is_array($body['tags'])); + } + + /** + * @expectedException \JPush\Exceptions\APIRequestException + * @expectedExceptionCode 7002 + */ + function testGetDevicesWithInvalidRid() { + $response = $this->device->getDevices('INVALID_REGISTRATION_ID'); + } + + function testUpdateDevicesAlias() { + global $registration_id; + $result = $this->device->getDevices($registration_id); + $old_alias = $result['body']['alias']; + if ($old_alias == null) { + $old_alias = ''; + } + $new_alias = 'jpush_alias'; + if ($old_alias == $new_alias) { + $new_alias = $new_alias . time(); + } + $response = $this->device->updateAlias($registration_id, $new_alias); + $this->assertEquals('200', $response['http_code']); + + $response = $this->device->updateAlias($registration_id, $old_alias); + $this->assertEquals('200', $response['http_code']); + } + + function testUpdateDevicesTags() { + global $registration_id; + $new_tag = $this->test_tag; + + $response = $this->device->addTags($registration_id, array($new_tag)); + $this->assertEquals('200', $response['http_code']); + + $response = $this->device->removeTags($registration_id, array($new_tag)); + $this->assertEquals('200', $response['http_code']); + } + + function testGetTags() { + $response = $this->device->getTags(); + $this->assertEquals('200', $response['http_code']); + + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertArrayHasKey('tags', $body); + } + + function testIsDeviceInTag() { + global $registration_id; + $test_tag = $this->test_tag; + + $this->device->addTags($registration_id, array($test_tag)); + $response = $this->device->isDeviceInTag($registration_id, $test_tag); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertTrue($body['result']); + + $this->device->removeTags($registration_id, array($test_tag)); + $response = $this->device->isDeviceInTag($registration_id, $test_tag); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertFalse($body['result']); + } + + function testUpdateTag() { + global $registration_id; + $test_tag = $this->test_tag; + + $response = $this->device->addDevicesToTag($test_tag, array($registration_id)); + $this->assertEquals('200', $response['http_code']); + + $response = $this->device->removeDevicesFromTag($test_tag, array($registration_id)); + $this->assertEquals('200', $response['http_code']); + } + + function testDeleteTag() {} + + function testGetAliasDevices() { + $test_tag = $this->test_tag; + + $response = $this->device->getAliasDevices($test_tag); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertArrayHasKey('registration_ids', $body); + } + + function testDeleteAlias() {} + + function testGetDevicesStatus() { + global $registration_id; + $response = $this->device->getDevicesStatus($registration_id); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + } + +} diff --git a/vendor/jpush/jpush/tests/JPush/PushPayloadTest.php b/vendor/jpush/jpush/tests/JPush/PushPayloadTest.php new file mode 100644 index 00000000..2bd300c7 --- /dev/null +++ b/vendor/jpush/jpush/tests/JPush/PushPayloadTest.php @@ -0,0 +1,315 @@ +payload = $client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello JPush'); + + $this->payload_without_audience = $client->push() + ->setPlatform('all') + ->setNotificationAlert('Hello JPush'); + } + + public function testSimplePushToAll() { + $payload = $this->payload; + $result = $payload->build(); + + $this->assertTrue(is_array($result)); + $this->assertEquals(4, count($result)); + $this->assertArrayHasKey('platform', $result); + $this->assertArrayHasKey('audience', $result); + $this->assertArrayHasKey('notification', $result); + $this->assertArrayHasKey('options', $result); + } + + public function testSetPlatform() { + $payload = $this->payload; + + $result = $payload->build(); + $this->assertEquals('all', $result['platform']); + + $result = $payload->setPlatform('ios')->build(); + $this->assertTrue(is_array($result['platform'])); + $this->assertEquals(1, count($result['platform'])); + $this->assertTrue(in_array('ios', $result['platform'])); + + $result = $payload->setPlatform(array('ios', 'android', 'blackberry'))->build(); + $this->assertTrue(is_array($result['platform'])); + $this->assertEquals(2, count($result['platform'])); + $this->assertFalse(in_array('blackberry', $result['platform'])); + } + + public function testSetAudience() { + $result = $this->payload->build(); + $this->assertEquals('all', $result['audience']); + } + + public function testAddTag() { + $payload = $this->payload_without_audience; + $result = $payload->addTag('hello')->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag'])); + $this->assertEquals(1, count($audience['tag'])); + + $result = $payload->addTag(array('jpush', 'jiguang'))->build(); + $this->assertEquals(3, count($result['audience']['tag'])); + } + public function testAddTag2() { + $payload = $this->payload_without_audience; + $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag_and'])); + $this->assertEquals(2, count($audience['tag_and'])); + + $result = $payload->addTagAnd('hello')->build(); + $this->assertEquals(3, count($result['audience']['tag_and'])); + } + + public function testAddTagAnd1() { + $payload = $this->payload_without_audience; + $result = $payload->addTagAnd('hello')->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag_and'])); + $this->assertEquals(1, count($audience['tag_and'])); + + $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build(); + $this->assertEquals(3, count($result['audience']['tag_and'])); + } + public function testAddTagAnd2() { + $payload = $this->payload_without_audience; + $result = $payload->addTagAnd(array('jpush', 'jiguang'))->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['tag_and'])); + $this->assertEquals(2, count($audience['tag_and'])); + + $result = $payload->addTagAnd('hello')->build(); + $this->assertEquals(3, count($result['audience']['tag_and'])); + } + + public function testAddRegistrationId1() { + $payload = $this->payload_without_audience; + $result = $payload->addRegistrationId('hello')->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['registration_id'])); + $this->assertEquals(1, count($audience['registration_id'])); + + $result = $payload->addRegistrationId(array('jpush', 'jiguang'))->build(); + $this->assertEquals(3, count($result['audience']['registration_id'])); + } + public function testAddRegistrationId2() { + $payload = $this->payload_without_audience; + $result = $payload->addRegistrationId(array('jpush', 'jiguang'))->build(); + $audience = $result['audience']; + $this->assertTrue(is_array($audience['registration_id'])); + $this->assertEquals(2, count($audience['registration_id'])); + + $result = $payload->addRegistrationId('hello')->build(); + $this->assertEquals(3, count($result['audience']['registration_id'])); + } + + public function testSetNotificationAlert() { + $result = $this->payload->build(); + $notification = $result['notification']; + $this->assertTrue(is_array($notification)); + $this->assertEquals(1, count($notification)); + $this->assertEquals('Hello JPush', $result['notification']['alert']); + } + + public function testIosNotification() { + $payload = $this->payload; + $result = $payload->iosNotification()->build(); + $ios = $result['notification']['ios']; + $this->assertTrue(is_array($ios)); + $this->assertEquals(3, count($ios)); + $this->assertArrayHasKey('alert', $ios); + $this->assertArrayHasKey('sound', $ios); + $this->assertArrayHasKey('badge', $ios); + $this->assertEquals('', $ios['alert']); + $this->assertEquals('', $ios['sound']); + $this->assertEquals('+1', $ios['badge']); + + $result = $payload->iosNotification('hello')->build(); + $ios = $result['notification']['ios']; + $this->assertEquals('hello', $result['notification']['ios']['alert']); + } + public function testIosNotificationWithArray() { + $payload = $this->payload; + $alert_array = array( + 'alert_k1' => 'alert_v1', + 'alert_k2' => 'alert_v2', + 'alert_k3' => 'alert_v3', + 'alert_k4' => 'alert_v4' + ); + $array = array( + 'sound' => 'jpush.caf', + 'badge' => 2, + 'content-available' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $result = $payload->iosNotification($alert_array, $array)->build(); + $ios = $result['notification']['ios']; + $this->assertTrue(is_array($ios['alert'])); + $this->assertEquals(6, count($ios)); + $this->assertFalse(array_key_exists('invalid_key', $ios)); + } + + public function testAndroidNotification() { + $payload = $this->payload; + $result = $payload->androidNotification()->build(); + $android = $result['notification']['android']; + $this->assertTrue(is_array($android)); + $this->assertEquals(1, count($android)); + $this->assertArrayHasKey('alert', $android); + $this->assertEquals('', $android['alert']); + + $result = $payload->androidNotification('hello')->build(); + $android = $result['notification']['android']; + $this->assertEquals('hello', $result['notification']['android']['alert']); + } + public function testAndroidNotificationWithArray() { + $payload = $this->payload; + $array = array( + 'title' => 'hello jpush', + 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $result = $payload->androidNotification('', $array)->build(); + $android = $result['notification']['android']; + $this->assertEquals(4, count($android)); + $this->assertFalse(array_key_exists('invalid_key', $android)); + } + + public function testSetSmsMessage() { + $payload = $this->payload; + $smsMessage = array( + 'delay_time' => 60, + 'signid' => 154, + 'temp_id' => 1, + 'temp_para' => array( + 'code' => 357 + ), + 'active_filter' => false + ); + $result = $payload->setSmsMessage($smsMessage)->build(); + $sms = $result['sms_message']; + $this->assertTrue(is_array($sms)); + $this->assertEquals(5, count($sms)); + $this->assertEquals(60, $sms['delay_time']); + $this->assertEquals(154, $sms['signid']); + $this->assertEquals(1, $sms['temp_id']); + } + + public function testMessage() { + $payload = $this->payload; + $result = $payload->message('Hello JPush')->build(); + $message = $result['message']; + $this->assertTrue(is_array($message)); + $this->assertEquals(1, count($message)); + $this->assertEquals('Hello JPush', $message['msg_content']); + + $array = array( + 'title' => 'hello jpush', + 'content_type' => '', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $result = $payload->message('Hello JPush', $array)->build(); + } + + public function testOptions() { + $payload = $this->payload; + $result = $payload->options()->build(); + $this->assertTrue(array_key_exists('options', $result)); + $this->assertEquals(false, $result['options']['apns_production']); + $this->assertTrue(array_key_exists('sendno', $result['options'])); + + $array = array( + 'sendno' => 100, + 'time_to_live' => 100, + 'apns_production' => true, + 'override_msg_id' => 100, + 'big_push_duration' => 100 + ); + $result = $payload->options($array)->build(); + $options = $result['options']; + $this->assertEquals(5, count($options)); + $this->assertArrayHasKey('apns_production', $options); + $this->assertEquals(true, $options['apns_production']); + } + + public function testPushToAll() { + $payload = $this->payload; + $platform = array('ios', 'android', 'blackberry'); + $ios_alert = array( + 'k1' => 'v1', + 'k2' => 'v2', + 'k3' => 'v3', + 'k4' => 'v4' + ); + $ios_notification = array( + 'sound' => 'jpush.caf', + 'badge' => 2, + 'content-available' => true, + 'category' => 'jiguang', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $android_notification = array( + 'title' => 'hello jpush', + 'builder_id' => 2, + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + $message = array( + 'title' => 'hello jpush', + 'content_type' => '', + 'extras' => array( + 'key' => 'value', + 'jiguang' + ), + 'invalid_key' => 'invalid_value' + ); + + $result = $payload->setPlatform($platform) + ->iosNotification($ios_alert, $ios_notification) + ->androidNotification('Hello Android', $android_notification) + ->message('Hello JPush', $message) + ->build(); + + $response = $payload->send(); + $this->assertEquals('200', $response['http_code']); + + echo "HTTP HEADERS ARE: "; + print_r($response['headers']); + + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + $this->assertArrayHasKey('sendno', $body); + $this->assertArrayHasKey('msg_id', $body); + } +} diff --git a/vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php b/vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php new file mode 100644 index 00000000..f86ca766 --- /dev/null +++ b/vendor/jpush/jpush/tests/JPush/ReportPayloadTest.php @@ -0,0 +1,77 @@ +payload = $client->push() + ->setPlatform('all') + ->addAllAudience() + ->setNotificationAlert('Hello JPush'); + $this->reporter = $client->report(); + } + + public function testPusher0() { + $payload = $this->payload; + $response = $payload->send(); + + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + $this->assertArrayHasKey('sendno', $body); + $this->assertArrayHasKey('msg_id', $body); + sleep(10); + return $body['msg_id']; + } + public function testPusher1() { + $payload = $this->payload; + $response = $payload->send(); + $this->assertEquals('200', $response['http_code']); + sleep(10); + return $response['body']['msg_id']; + } + + /** + * @depends testPusher0 + * @depends testPusher1 + */ + public function testGetReceived($msg_id_0, $msg_id_1) { + $response = $this->reporter->getReceived($msg_id_0); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertTrue(is_array($body[0])); + $this->assertArrayHasKey('msg_id', $body[0]); + + $response = $this->reporter->getReceived(array($msg_id_0, $msg_id_1)); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + } + + /** + * @depends testPusher0 + * @depends testPusher1 + */ + public function testGetMessages($msg_id_0, $msg_id_1) { + $response = $this->reporter->getMessages($msg_id_0); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(1, count($body)); + $this->assertTrue(is_array($body[0])); + $this->assertEquals(4, count($body[0])); + $this->assertArrayHasKey('msg_id', $body[0]); + + $response = $this->reporter->getMessages(array($msg_id_0, $msg_id_1)); + $this->assertEquals('200', $response['http_code']); + $body = $response['body']; + $this->assertTrue(is_array($body)); + $this->assertEquals(2, count($body)); + } +} diff --git a/vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php b/vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php new file mode 100644 index 00000000..391738e1 --- /dev/null +++ b/vendor/jpush/jpush/tests/JPush/SchedulePayloadTest.php @@ -0,0 +1,18 @@ +schedule = $client->schedule(); + } + + public function testGetSchedules() { + $schedule = $this->schedule; + $response = $schedule->getSchedules(); + $this->assertEquals('200', $response['http_code']); + } + +} diff --git a/vendor/jpush/jpush/tests/bootstrap.php b/vendor/jpush/jpush/tests/bootstrap.php new file mode 100644 index 00000000..bfe7e844 --- /dev/null +++ b/vendor/jpush/jpush/tests/bootstrap.php @@ -0,0 +1,8 @@ + Date: Thu, 29 Jun 2023 13:48:22 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E7=BB=93=E7=AE=97=E5=90=8E=E7=9A=84=E5=88=A9=E6=81=AF=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repositories/store/order/StoreOrderRepository.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/common/repositories/store/order/StoreOrderRepository.php b/app/common/repositories/store/order/StoreOrderRepository.php index d5632846..0fd7f9d7 100644 --- a/app/common/repositories/store/order/StoreOrderRepository.php +++ b/app/common/repositories/store/order/StoreOrderRepository.php @@ -1692,10 +1692,12 @@ class StoreOrderRepository extends BaseRepository } if ($order->pay_type == StoreGroupOrder::PAY_TYPE_CREDIT_BUY && $order->interest) { $order->interest_start_time = $order->interest->start_time; - $days = ceil((time() - strtotime($order->interest->start_time)) / 86400); - $interestMoney = bcmul($order->interest->total_price, $order->interest->rate, 2); - $order->interest_money = bcmul($days, $interestMoney, 2); $order->interest_status = $order->interest->status; + if ($order->interest_status == StoreOrderInterest::STATUS_SETTLED) { + $order->interest_money = $order->interest->interest; + } else { + $order->interest_money = $order->interest->calculateInterest(); + } } $order->takeOrderCount = count($order['takeOrderList']); unset($order['takeOrderList'], $order->interest); @@ -2471,6 +2473,7 @@ class StoreOrderRepository extends BaseRepository if ($result === true) { $groupOrder->interest->status = StoreOrderInterest::STATUS_SETTLED; $groupOrder->interest->settle_time = date('Y-m-d H:i:s'); + $groupOrder->interest->interest = $interest; $groupOrder->interest->save(); /** @var UserBillRepository $userBillRepository */ From 0b4dcf19ead46a61addf5d15a93e010820d5239d Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Sat, 1 Jul 2023 13:51:35 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E8=B0=83=E8=AF=95=E9=87=87=E8=B4=AD?= =?UTF-8?q?=E5=95=86=E5=93=81=E4=BF=A1=E7=94=A8=E8=B4=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/dao/store/order/StoreCartDao.php | 2 +- app/common/dao/system/merchant/MerchantDao.php | 3 +++ .../repositories/store/order/StoreOrderCreateRepository.php | 5 ++++- .../repositories/system/merchant/MerchantRepository.php | 2 +- app/controller/api/store/merchant/Merchant.php | 2 +- app/validate/merchant/MerchantUpdateValidate.php | 1 + 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/common/dao/store/order/StoreCartDao.php b/app/common/dao/store/order/StoreCartDao.php index aa2e64e0..5aa780f8 100644 --- a/app/common/dao/store/order/StoreCartDao.php +++ b/app/common/dao/store/order/StoreCartDao.php @@ -114,7 +114,7 @@ class StoreCartDao extends BaseDao ->append(['bc_extension_one', 'bc_extension_two']); }, 'merchant' => function (Relation $query) use ($uid) { - $query->field('mer_id,mer_name,mer_state,mer_avatar,delivery_way,commission_rate,category_id,credit_buy')->with(['coupon' => function ($query) use ($uid) { + $query->field('mer_id,mer_name,mer_state,mer_avatar,delivery_way,commission_rate,category_id,credit_buy,settle_cycle,interest_rate')->with(['coupon' => function ($query) use ($uid) { $query->where('uid', $uid); }, 'config' => function ($query) { diff --git a/app/common/dao/system/merchant/MerchantDao.php b/app/common/dao/system/merchant/MerchantDao.php index 26b2c45d..c3e34e04 100644 --- a/app/common/dao/system/merchant/MerchantDao.php +++ b/app/common/dao/system/merchant/MerchantDao.php @@ -49,6 +49,9 @@ class MerchantDao extends BaseDao ->when($is_del !== null, function ($query) use ($is_del) { $query->where('is_del', $is_del); }) + ->when(isset($where['credit_buy']) && $where['credit_buy'] !== '', function ($query) use ($where) { + $query->where('credit_buy', $where['credit_buy']); + }) ->when(isset($where['is_trader']) && $where['is_trader'] !== '', function ($query) use ($where) { $query->where('is_trader', $where['is_trader']); }) diff --git a/app/common/repositories/store/order/StoreOrderCreateRepository.php b/app/common/repositories/store/order/StoreOrderCreateRepository.php index 20962a0f..b279b969 100644 --- a/app/common/repositories/store/order/StoreOrderCreateRepository.php +++ b/app/common/repositories/store/order/StoreOrderCreateRepository.php @@ -96,6 +96,9 @@ class StoreOrderCreateRepository extends StoreOrderRepository } } } + if ($order_type == 98 && count($merchantCartList) > 1) { + throw new ValidateException('采购商品不支持跨店购买'); + } unset($merchantCart, $cart); $order_price = 0; @@ -925,7 +928,7 @@ class StoreOrderCreateRepository extends StoreOrderRepository $extend = []; } $orderType = $orderInfo['order_type']; - if (!in_array($orderType, [98, 0]) && (count($orderInfo['order']) > 1 || ($orderType != 10 && count($orderInfo['order'][0]['list']) > 1))) { + if ($orderType != 0 && (count($orderInfo['order']) > 1 || ($orderType != 10 && count($orderInfo['order'][0]['list']) > 1))) { throw new ValidateException('活动商品请单独购买'); } diff --git a/app/common/repositories/system/merchant/MerchantRepository.php b/app/common/repositories/system/merchant/MerchantRepository.php index e1658f69..3b2b27ac 100644 --- a/app/common/repositories/system/merchant/MerchantRepository.php +++ b/app/common/repositories/system/merchant/MerchantRepository.php @@ -290,7 +290,7 @@ class MerchantRepository extends BaseRepository */ public function getList($where, $page, $limit, $userInfo) { - $field = 'care_count,is_trader,type_id,mer_id,mer_banner,mini_banner,mer_name, mark,mer_avatar,product_score,service_score,postage_score,sales,status,is_best,create_time,long,lat,is_margin,service_phone,mer_address,mer_info'; + $field = 'care_count,is_trader,type_id,mer_id,mer_banner,mini_banner,mer_name, mark,mer_avatar,product_score,service_score,postage_score,sales,status,is_best,create_time,long,lat,is_margin,service_phone,mer_address,mer_info,credit_buy,settle_cycle,interest_rate'; $where['status'] = 1; $where['mer_state'] = 1; $where['is_del'] = 0; diff --git a/app/controller/api/store/merchant/Merchant.php b/app/controller/api/store/merchant/Merchant.php index f9b33448..81e7a929 100644 --- a/app/controller/api/store/merchant/Merchant.php +++ b/app/controller/api/store/merchant/Merchant.php @@ -54,7 +54,7 @@ class Merchant extends BaseController public function lst() { [$page, $limit] = $this->getPage(); - $where = $this->request->params(['keyword', 'order', 'is_best', 'location', 'category_id', 'type_id','is_trader', 'street_id']); + $where = $this->request->params(['keyword', 'order', 'is_best', 'location', 'category_id', 'type_id','is_trader', 'street_id', 'credit_buy']); if (empty($where['type_id'])) { $where['type_id'] = [MerchantModel::TypeCloudWarehouse, MerchantModel::TypeStore, MerchantModel::TypeSupplyChain, MerchantModel::TypePlatform]; } diff --git a/app/validate/merchant/MerchantUpdateValidate.php b/app/validate/merchant/MerchantUpdateValidate.php index 21e7aeb4..80c6a53a 100644 --- a/app/validate/merchant/MerchantUpdateValidate.php +++ b/app/validate/merchant/MerchantUpdateValidate.php @@ -29,6 +29,7 @@ class MerchantUpdateValidate extends Validate 'mer_address|店铺地址' => 'require|max:128', 'long|店铺经度' => 'max:24', 'lat|店铺纬度' => 'max:24', + 'interest_rate|利率' => 'max:0.05', ]; protected function isPhone($val) From 01df202cb733353fd227c07872debedcd9851bd9 Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Tue, 4 Jul 2023 11:13:39 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E4=BF=A1=E7=94=A8=E8=B4=AD=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E6=B7=BB=E5=8A=A0=E7=A1=AE=E8=AE=A4=E6=8E=A5=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/model/store/order/StoreOrder.php | 3 ++ .../order/StoreOrderCreateRepository.php | 4 +++ .../store/order/StoreOrderRepository.php | 32 +++++++++++++++++++ app/controller/api/store/order/StoreOrder.php | 19 +++++++++-- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/app/common/model/store/order/StoreOrder.php b/app/common/model/store/order/StoreOrder.php index 2a145adb..9a4ebdd2 100644 --- a/app/common/model/store/order/StoreOrder.php +++ b/app/common/model/store/order/StoreOrder.php @@ -26,6 +26,9 @@ use app\common\repositories\store\MerchantTakeRepository; class StoreOrder extends BaseModel { + const STATUS_WAIT_CONFIRM = 12; //待确认 + const STATUS_WAIT_PAY = 0; //待支付 + public static function tablePk(): ?string { return 'order_id'; diff --git a/app/common/repositories/store/order/StoreOrderCreateRepository.php b/app/common/repositories/store/order/StoreOrderCreateRepository.php index b279b969..250916b1 100644 --- a/app/common/repositories/store/order/StoreOrderCreateRepository.php +++ b/app/common/repositories/store/order/StoreOrderCreateRepository.php @@ -4,6 +4,7 @@ namespace app\common\repositories\store\order; use app\common\dao\store\order\StoreCartDao; use app\common\model\store\order\StoreGroupOrder; +use app\common\model\store\order\StoreOrder; use app\common\repositories\store\coupon\StoreCouponRepository; use app\common\repositories\store\coupon\StoreCouponUserRepository; use app\common\repositories\store\product\ProductAssistSkuRepository; @@ -1219,6 +1220,9 @@ class StoreOrderCreateRepository extends StoreOrderRepository $orderProduct = []; $orderStatus = []; foreach ($orderList as $order) { + if ($order['pay_type'] == StoreGroupOrder::PAY_TYPE_CREDIT_BUY) { + $order['status'] = StoreOrder::STATUS_WAIT_CONFIRM; + } $cartInfo = $order['cartInfo']; unset($order['cartInfo']); //创建子订单 diff --git a/app/common/repositories/store/order/StoreOrderRepository.php b/app/common/repositories/store/order/StoreOrderRepository.php index 0fd7f9d7..c88f9c65 100644 --- a/app/common/repositories/store/order/StoreOrderRepository.php +++ b/app/common/repositories/store/order/StoreOrderRepository.php @@ -2495,4 +2495,36 @@ class StoreOrderRepository extends BaseRepository } } + /** + * 确认接单 + * @param $user + * @param $id + * @return void + * @throws Exception + */ + public function confirm($user, $id) + { + /** @var StoreGroupOrderRepository $groupOrderRepository */ + $groupOrderRepository = app()->make(StoreGroupOrderRepository::class); + $groupOrderRepository->getAll = true; + Db::startTrans(); + try { + $groupOrder = $groupOrderRepository->detail($user['uid'], $id, false); + if ($groupOrder->pay_type != StoreGroupOrder::PAY_TYPE_CREDIT_BUY) { + throw new Exception('订单类型错误'); + } + $order = $groupOrder->orderList[0]; + if ($order->status != StoreOrder::STATUS_WAIT_CONFIRM) { + throw new Exception('订单状态错误'); + } + $order->status = StoreOrder::STATUS_WAIT_PAY; + $order->save(); + Db::commit(); + } catch (\Exception $e) { + Db::rollback(); + throw new Exception($e->getMessage()); + } + + } + } diff --git a/app/controller/api/store/order/StoreOrder.php b/app/controller/api/store/order/StoreOrder.php index 52981133..c6e8529c 100644 --- a/app/controller/api/store/order/StoreOrder.php +++ b/app/controller/api/store/order/StoreOrder.php @@ -106,11 +106,11 @@ class StoreOrder extends BaseController return $orderCreateRepository->v2CreateOrder(array_search($payType, StoreOrderRepository::PAY_TYPE), $this->request->userInfo(), $cartId, $extend, $mark, $receipt_data, $takes, $couponIds, $useIntegral, $addressId, $post); }); - if ($groupOrder['pay_price'] == 0 || $groupOrder['pay_type'] == StoreGroupOrder::PAY_TYPE_CREDIT_BUY) { + if ($groupOrder['pay_price'] == 0) { $this->repository->paySuccess($groupOrder); return app('json')->status('success', '支付成功', ['order_id' => $groupOrder['group_order_id']]); } - if ($isPc) { + if ($isPc || $groupOrder['pay_type'] == StoreGroupOrder::PAY_TYPE_CREDIT_BUY) { return app('json')->success(['order_id' => $groupOrder->group_order_id]); } try { @@ -316,4 +316,19 @@ class StoreOrder extends BaseController } } + /** + * 确认接单 + * @return mixed + */ + public function confirm() + { + $id = $this->request->param('id/d'); + try { + $this->repository->confirm($this->request->userInfo(), $id); + return app('json')->success('success'); + } catch (\Exception $e) { + return app('json')->fail($e->getMessage()); + } + } + } From 69c339fc5a6f0e0f13e3e2443d002dcf46d69629 Mon Sep 17 00:00:00 2001 From: luofei <604446095@qq.com> Date: Tue, 4 Jul 2023 14:39:52 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=A1=E7=94=A8=E8=B4=AD=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E9=80=BE=E6=9C=9F=EF=BC=8C=E5=86=BB=E7=BB=93=E5=95=86?= =?UTF-8?q?=E6=88=B7=E6=8F=90=E7=8E=B0=EF=BC=8C=E7=BB=93=E7=AE=97=E5=90=8E?= =?UTF-8?q?=E6=81=A2=E5=A4=8D=E6=8F=90=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/model/store/order/StoreOrder.php | 5 +++ .../store/order/StoreOrderRepository.php | 6 ++++ .../system/merchant/MerchantRepository.php | 29 +++++++++++++++ .../api/store/merchant/Merchant.php | 3 ++ app/controller/api/store/order/StoreOrder.php | 3 ++ app/event.php | 1 + app/listener/OrderTake.php | 1 + crmeb/listens/AutoUnfreezeMerchantListen.php | 35 +++++++++++++++++++ route/api.php | 1 + 9 files changed, 84 insertions(+) create mode 100644 crmeb/listens/AutoUnfreezeMerchantListen.php diff --git a/app/common/model/store/order/StoreOrder.php b/app/common/model/store/order/StoreOrder.php index 9a4ebdd2..c57dd5b3 100644 --- a/app/common/model/store/order/StoreOrder.php +++ b/app/common/model/store/order/StoreOrder.php @@ -186,4 +186,9 @@ class StoreOrder extends BaseModel return $this->hasOne(StoreOrderInterest::class, 'order_id', 'order_id'); } + public function allowCreditPay() + { + return $this->pay_type == StoreGroupOrder::PAY_TYPE_CREDIT_BUY && $this->status == self::STATUS_WAIT_PAY; + } + } diff --git a/app/common/repositories/store/order/StoreOrderRepository.php b/app/common/repositories/store/order/StoreOrderRepository.php index c88f9c65..fad9f4e3 100644 --- a/app/common/repositories/store/order/StoreOrderRepository.php +++ b/app/common/repositories/store/order/StoreOrderRepository.php @@ -2486,6 +2486,12 @@ class StoreOrderRepository extends BaseRepository 'mark' => '余额支付支付' . floatval($groupOrder['pay_price']) . '元购买商品', 'balance' => $user->now_money ]); + $unSettleCount = StoreOrderInterest::where('mer_id', $groupOrder->interest->mer_id)->where('status', 0)->count(); + if ($unSettleCount === 0) { + /** @var MerchantRepository $merchantRepo */ + $merchantRepo = app()->make(MerchantRepository::class); + $merchantRepo->unfreeze($groupOrder->interest->mer_id); + } } Db::commit(); return $data; diff --git a/app/common/repositories/system/merchant/MerchantRepository.php b/app/common/repositories/system/merchant/MerchantRepository.php index 3b2b27ac..b9869c7e 100644 --- a/app/common/repositories/system/merchant/MerchantRepository.php +++ b/app/common/repositories/system/merchant/MerchantRepository.php @@ -743,5 +743,34 @@ class MerchantRepository extends BaseRepository return [$income, $finance, true]; } + /** + * 冻结商户提现 + * @param $merchantId + * @return void + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function freeze($merchantId) + { + $merchant = $this->get($merchantId); + $merchant->is_fronze = 1; + $merchant->save(); + } + + /** + * 解冻商户提现 + * @param $merchantId + * @return void + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function unfreeze($merchantId) + { + $merchant = $this->get($merchantId); + $merchant->is_fronze = 0; + $merchant->save(); + } } diff --git a/app/controller/api/store/merchant/Merchant.php b/app/controller/api/store/merchant/Merchant.php index 81e7a929..cbd1f7bf 100644 --- a/app/controller/api/store/merchant/Merchant.php +++ b/app/controller/api/store/merchant/Merchant.php @@ -283,6 +283,9 @@ class Merchant extends BaseController if ($this->userInfo['uid'] != $merchant->uid){ return app('json')->fail('你不是管理员无法进行提现操作'); } + if ($merchant->is_frozen){ + return app('json')->fail('账户被冻结,无法进行提现操作'); + } $bankInfo = [ 'name' => $data['financial_bank_name'], 'bank' => $data['financial_bank_bank'], diff --git a/app/controller/api/store/order/StoreOrder.php b/app/controller/api/store/order/StoreOrder.php index c6e8529c..09047bf5 100644 --- a/app/controller/api/store/order/StoreOrder.php +++ b/app/controller/api/store/order/StoreOrder.php @@ -240,6 +240,9 @@ class StoreOrder extends BaseController if (!$groupOrder) return app('json')->fail('订单不存在或已支付'); $this->repository->changePayType($groupOrder, array_search($type, StoreOrderRepository::PAY_TYPE)); + if ($groupOrder['pay_type'] == StoreGroupOrder::PAY_TYPE_CREDIT_BUY && !$groupOrder->orderList[0]->allowCreditPay()) { + return app('json')->fail('请等待商家确认订单'); + } if ($groupOrder['pay_price'] == 0 || $groupOrder['pay_type'] == StoreGroupOrder::PAY_TYPE_CREDIT_BUY) { $this->repository->paySuccess($groupOrder); return app('json')->status('success', '支付成功', ['order_id' => $groupOrder['group_order_id']]); diff --git a/app/event.php b/app/event.php index 089e8908..cc18c4ad 100644 --- a/app/event.php +++ b/app/event.php @@ -55,6 +55,7 @@ return [ \crmeb\listens\AuthCancelActivityListen::class, \crmeb\listens\CloseUserSvipListen::class, \crmeb\listens\SendSvipCouponListen::class, + \crmeb\listens\AutoUnfreezeMerchantListen::class, ] : [], 'pay_success_user_recharge' => [\crmeb\listens\pay\UserRechargeSuccessListen::class], 'pay_success_user_order' => [\crmeb\listens\pay\UserOrderSuccessListen::class], diff --git a/app/listener/OrderTake.php b/app/listener/OrderTake.php index 859e6c3b..96a81048 100644 --- a/app/listener/OrderTake.php +++ b/app/listener/OrderTake.php @@ -23,6 +23,7 @@ class OrderTake $storeOrderInterestRepository = app()->make(StoreOrderInterestRepository::class); $merchantId = Merchant::where('uid', $order['uid'])->value('mer_id'); $data = [ + 'group_order_id' => $order['group_order_id'], 'order_id' => $order['order_id'], 'mer_id' => $merchantId, 'to_mer_id' => $order['mer_id'], diff --git a/crmeb/listens/AutoUnfreezeMerchantListen.php b/crmeb/listens/AutoUnfreezeMerchantListen.php new file mode 100644 index 00000000..ad91d8b0 --- /dev/null +++ b/crmeb/listens/AutoUnfreezeMerchantListen.php @@ -0,0 +1,35 @@ + +// +---------------------------------------------------------------------- + + +namespace crmeb\listens; + + +use app\common\model\store\order\StoreOrderInterest; +use app\common\repositories\system\merchant\MerchantRepository; +use crmeb\interfaces\ListenerInterface; +use crmeb\services\TimerService; + +class AutoUnfreezeMerchantListen extends TimerService implements ListenerInterface +{ + public function handle($event): void + { + $this->tick(1000 * 60, function () { + request()->clearCache(); + $unSettle = StoreOrderInterest::whereTime('start_time', '<=', time())->where('status', 0)->group('mer_id')->column('mer_id'); + /** @var MerchantRepository $merchantRepo */ + $merchantRepo = app()->make(MerchantRepository::class); + foreach ($unSettle as $merId) { + $merchantRepo->freeze($merId); + } + }); + } +} diff --git a/route/api.php b/route/api.php index 72ba6e29..9dbb2448 100644 --- a/route/api.php +++ b/route/api.php @@ -91,6 +91,7 @@ Route::group('api/', function () { Route::post('receipt/:id', '/createReceipt'); Route::get('delivery/:id', '/getOrderDelivery'); Route::post('settle', '/settle'); + Route::post('confirm', '/confirm'); })->prefix('api.store.order.StoreOrder'); // 预售