From 75174a99df1e6dc752cc119c2c7ffe752c6cf74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=98=8A=E5=A4=A9?= <442384644@qq.com> Date: Tue, 27 Sep 2022 16:04:04 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E7=A8=8B=E5=BA=8F=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E3=80=91=E4=BC=98=E5=8C=96=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crmeb/app/adminapi/controller/Common.php | 2 +- .../marketing/integral/StoreIntegralOrder.php | 2 +- .../controller/v1/order/StoreOrder.php | 2 +- .../controller/v1/product/StoreProduct.php | 28 ++ .../controller/v1/setting/LangCountry.php | 21 +- .../controller/v1/setting/SystemAdmin.php | 20 +- .../controller/v1/setting/SystemConfig.php | 19 +- crmeb/app/adminapi/route/product.php | 5 + crmeb/app/adminapi/route/setting.php | 12 +- crmeb/app/adminapi/route/system.php | 6 +- crmeb/app/api/controller/v1/PayController.php | 9 +- .../v1/order/StoreIntegralOrderController.php | 2 +- .../v1/order/StoreOrderController.php | 4 +- .../controller/v1/wechat/WechatController.php | 5 + crmeb/app/api/route/v1.php | 1 + .../dao/product/product/StoreProductDao.php | 4 +- .../order/StoreOrderRefundServices.php | 7 +- .../app/services/order/StoreOrderServices.php | 1 + crmeb/app/services/pay/PayServices.php | 6 +- .../product/product/StoreProductServices.php | 95 +++++ .../app/services/shipping/ExpressServices.php | 4 +- .../system/admin/SystemAdminServices.php | 26 +- .../system/config/SystemConfigServices.php | 14 +- .../services/system/lang/LangCodeServices.php | 4 +- .../system/lang/LangCountryServices.php | 45 +- crmeb/app/services/wechat/WechatServices.php | 16 + crmeb/crmeb/services/app/WechatService.php | 14 +- .../crmeb/services/easywechat/Application.php | 9 +- .../easywechat/miniPayment/WeChatClient.php | 34 +- .../services/easywechat/v3pay/BaseClient.php | 280 ++++++++++++ .../services/easywechat/v3pay/Certficates.php | 68 +++ .../services/easywechat/v3pay/PayClient.php | 400 ++++++++++++++++++ .../easywechat/v3pay/ServiceProvider.php | 36 ++ .../services/express/storage/Express.php | 7 +- crmeb/crmeb/services/pay/Pay.php | 2 + crmeb/crmeb/services/pay/PayInterface.php | 2 +- .../services/pay/storage/V3WechatPay.php | 216 ++++++++++ .../crmeb/services/pay/storage/WechatPay.php | 12 +- crmeb/public/install/crmeb.sql | 56 ++- crmeb/vendor/composer/installed.php | 12 +- .../wechat/src/Foundation/Application.php | 6 +- crmeb/vendor/services.php | 2 +- 42 files changed, 1395 insertions(+), 121 deletions(-) create mode 100644 crmeb/crmeb/services/easywechat/v3pay/BaseClient.php create mode 100644 crmeb/crmeb/services/easywechat/v3pay/Certficates.php create mode 100644 crmeb/crmeb/services/easywechat/v3pay/PayClient.php create mode 100644 crmeb/crmeb/services/easywechat/v3pay/ServiceProvider.php create mode 100644 crmeb/crmeb/services/pay/storage/V3WechatPay.php diff --git a/crmeb/app/adminapi/controller/Common.php b/crmeb/app/adminapi/controller/Common.php index 3aca336e2..88536a106 100644 --- a/crmeb/app/adminapi/controller/Common.php +++ b/crmeb/app/adminapi/controller/Common.php @@ -111,7 +111,7 @@ class Common extends AuthController } catch (\Throwable $e) { return app('json')->fail(400330); } - return app('json')->success(['status' => 1, 'copyright' => $this->copyright(), 'authCode' => $authCode, 'day' => 0, 'force_reminder' => $upgradeStatus['force_reminder'] ?? 0]); + return app('json')->success(['status' => 1, 'copyright' => $res['data']['copyright'], 'authCode' => $authCode, 'day' => 0, 'force_reminder' => $upgradeStatus['force_reminder'] ?? 0]); default: return app('json')->success(['status' => -9, 'force_reminder' => $upgradeStatus['force_reminder'] ?? 0]); } diff --git a/crmeb/app/adminapi/controller/v1/marketing/integral/StoreIntegralOrder.php b/crmeb/app/adminapi/controller/v1/marketing/integral/StoreIntegralOrder.php index 99add057a..2e277f853 100644 --- a/crmeb/app/adminapi/controller/v1/marketing/integral/StoreIntegralOrder.php +++ b/crmeb/app/adminapi/controller/v1/marketing/integral/StoreIntegralOrder.php @@ -216,7 +216,7 @@ class StoreIntegralOrder extends AuthController $data['delivery_name'] = $orderInfo['delivery_name']; $data['delivery_id'] = $orderInfo['delivery_id']; - $data['result'] = $services->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code'] ?? null); + $data['result'] = $services->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code'] ?? null, $orderInfo['user_phone']); return app('json')->success($data); } diff --git a/crmeb/app/adminapi/controller/v1/order/StoreOrder.php b/crmeb/app/adminapi/controller/v1/order/StoreOrder.php index b0be12b8e..5414daa6e 100644 --- a/crmeb/app/adminapi/controller/v1/order/StoreOrder.php +++ b/crmeb/app/adminapi/controller/v1/order/StoreOrder.php @@ -510,7 +510,7 @@ class StoreOrder extends AuthController $data['delivery_name'] = $orderInfo['delivery_name']; $data['delivery_id'] = $orderInfo['delivery_id']; - $data['result'] = $services->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code'] ?? null); + $data['result'] = $services->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code'] ?? null, $orderInfo['user_phone']); return app('json')->success($data); } diff --git a/crmeb/app/adminapi/controller/v1/product/StoreProduct.php b/crmeb/app/adminapi/controller/v1/product/StoreProduct.php index 394ffda41..aefb305dc 100644 --- a/crmeb/app/adminapi/controller/v1/product/StoreProduct.php +++ b/crmeb/app/adminapi/controller/v1/product/StoreProduct.php @@ -359,6 +359,11 @@ class StoreProduct extends AuthController return app('json')->success(100002); } + /** + * 导入卡密 + * @return mixed + * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception + */ public function import_card() { $data = $this->request->getMore([ @@ -371,4 +376,27 @@ class StoreProduct extends AuthController $cardData = $readExcelService->readExcel($file); return app('json')->success($cardData); } + + /** + * 商品批量设置 + * @return mixed + */ + public function batchSetting() + { + $data = $this->request->postMore([ + ['ids', []], + ['cate_id', []], + ['logistics', []], + ['freight', 2], + ['postage', 0], + ['temp_id', 1], + ['give_integral', 0], + ['coupon_ids', []], + ['label_id', []], + ['recommend', []], + ['type', 0] + ]); + $this->service->batchSetting($data); + return app('json')->success(100014); + } } diff --git a/crmeb/app/adminapi/controller/v1/setting/LangCountry.php b/crmeb/app/adminapi/controller/v1/setting/LangCountry.php index 8bbed0d45..5b3b50745 100644 --- a/crmeb/app/adminapi/controller/v1/setting/LangCountry.php +++ b/crmeb/app/adminapi/controller/v1/setting/LangCountry.php @@ -50,22 +50,29 @@ class LangCountry extends AuthController * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function langCountryTypeForm($id) + public function langCountryForm($id) { - return app('json')->success($this->services->LangCountryTypeForm($id)); + return app('json')->success($this->services->langCountryForm($id)); } /** - * 国家语言修改 + * 地区语言修改 * @param $id * @return mixed */ public function langCountrySave($id) { - [$typeId] = $this->request->postMore([ - ['type', 0], - ], true); - $this->services->langCountrySave($id, $typeId); + $data = $this->request->postMore([ + ['name', ''], + ['code', ''], + ]); + $this->services->langCountrySave($id, $data); return app('json')->success(100000); } + + public function langCountryDel($id) + { + $this->services->langCountryDel($id); + return app('json')->success(100002); + } } \ No newline at end of file diff --git a/crmeb/app/adminapi/controller/v1/setting/SystemAdmin.php b/crmeb/app/adminapi/controller/v1/setting/SystemAdmin.php index 5920e7ea5..907279ab0 100644 --- a/crmeb/app/adminapi/controller/v1/setting/SystemAdmin.php +++ b/crmeb/app/adminapi/controller/v1/setting/SystemAdmin.php @@ -168,8 +168,6 @@ class SystemAdmin extends AuthController ['pwd', ''], ['new_pwd', ''], ['conf_pwd', ''], - ['file_pwd', ''], - ['conf_file_pwd', ''], ]); if(!preg_match('/^(?![^a-zA-Z]+$)(?!\D+$).{6,}$/',$data['new_pwd'])){ return app('json')->fail(400183); @@ -179,6 +177,24 @@ class SystemAdmin extends AuthController else return app('json')->fail(100007); } + /** + * 修改当前登陆admin的文件管理密码 + * @return mixed + */ + public function set_file_password() + { + $data = $this->request->postMore([ + ['file_pwd', ''], + ['conf_file_pwd', ''], + ]); + if(!preg_match('/^(?![^a-zA-Z]+$)(?!\D+$).{6,}$/',$data['file_pwd'])){ + return app('json')->fail(400183); + } + if ($this->services->setFilePassword($this->adminId, $data)) + return app('json')->success(100001); + else + return app('json')->fail(100007); + } /** * 退出登陆 diff --git a/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php b/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php index cf01d319a..61b797af3 100644 --- a/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php +++ b/crmeb/app/adminapi/controller/v1/setting/SystemConfig.php @@ -12,6 +12,7 @@ namespace app\adminapi\controller\v1\setting; use app\adminapi\controller\AuthController; use app\Request; +use app\services\order\StoreOrderServices; use app\services\system\config\SystemConfigServices; use app\services\system\config\SystemConfigTabServices; use think\facade\App; @@ -301,13 +302,21 @@ class SystemConfig extends AuthController if (isset($post['day_brokerage_price_upper']) && $post['day_brokerage_price_upper'] < -1) { return app('json')->fail(400757); } - if( isset($post['pay_new_weixin_open']) && (bool)$post['pay_new_weixin_open']) - { - if(empty($post['pay_new_weixin_mchid'])) - { - return app('json')->fail(400763); + if (isset($post['pay_new_weixin_open']) && (bool)$post['pay_new_weixin_open']) { + if (empty($post['pay_new_weixin_mchid'])) { + return app('json')->fail(400763); } } + + //支付接口类型选择,如果有订单就不能再进行切换 + if (isset($post['pay_wechat_type'])) { + /** @var StoreOrderServices $orderServices */ + $orderServices = app()->make(StoreOrderServices::class); + if ($post['pay_wechat_type'] != -1 && $orderServices->count()) { + return app('json')->fail('支付接口类型已经选择,不能再次进行切换,切换后会导致无法退款等问题。'); + } + } + if (isset($post['weixin_ckeck_file'])) { $from = public_path() . $post['weixin_ckeck_file']; $to = public_path() . array_reverse(explode('/', $post['weixin_ckeck_file']))[0]; diff --git a/crmeb/app/adminapi/route/product.php b/crmeb/app/adminapi/route/product.php index 4bd750cf1..ecc05ee87 100644 --- a/crmeb/app/adminapi/route/product.php +++ b/crmeb/app/adminapi/route/product.php @@ -93,6 +93,11 @@ Route::group('product', function () { Route::get('product/check_activity/:id', 'v1.product.StoreProduct/check_activity')->option(['real_name' => '检测是商品否有活动开启']); //导入虚拟商品卡密 Route::get('product/import_card', 'v1.product.StoreProduct/import_card')->option(['real_name' => '导入虚拟商品卡密']); + + /** 商品批量操作 */ + Route::post('batch/setting', 'v1.product.StoreProduct/batchSetting')->option(['real_name' => '商品批量设置']); + + })->middleware([ \app\http\middleware\AllowOriginMiddleware::class, \app\adminapi\middleware\AdminAuthTokenMiddleware::class, diff --git a/crmeb/app/adminapi/route/setting.php b/crmeb/app/adminapi/route/setting.php index 8f3692ff6..e0f5df30c 100644 --- a/crmeb/app/adminapi/route/setting.php +++ b/crmeb/app/adminapi/route/setting.php @@ -25,6 +25,8 @@ Route::group('setting', function () { Route::get('info', 'v1.setting.SystemAdmin/info')->name('SystemAdminInfo')->option(['real_name' => '获取当前管理员信息']); //修改当前管理员信息 Route::put('update_admin', 'v1.setting.SystemAdmin/update_admin')->name('SystemAdminUpdateAdmin')->option(['real_name' => '修改当前管理员信息']); + //设置文件管理密码 + Route::put('set_file_password', 'v1.setting.SystemAdmin/set_file_password')->name('SystemAdminSetFilePassword')->option(['real_name' => '设置当前文件管理密码']); //权限菜单资源路由 Route::resource('menus', 'v1.setting.SystemMenus')->option(['real_name' => '权限菜单']); //未添加的权限规则列表 @@ -169,10 +171,12 @@ Route::group('setting', function () { /** 多语言 */ //语言国家列表 Route::get('lang_country/list', 'v1.setting.LangCountry/langCountryList')->option(['real_name' => '语言国家列表']); - //设置国家语言类型表单 - Route::get('lang_country/type_form/:id', 'v1.setting.LangCountry/langCountryTypeForm')->option(['real_name' => '设置国家语言类型表单']); - //语言类型列表 - Route::post('lang_country/save/:id', 'v1.setting.LangCountry/langCountrySave')->option(['real_name' => '语言国家修改']); + //添加语言地区表单 + Route::get('lang_country/form/:id', 'v1.setting.LangCountry/langCountryForm')->option(['real_name' => '添加语言地区表单']); + //保存语言地区 + Route::post('lang_country/save/:id', 'v1.setting.LangCountry/langCountrySave')->option(['real_name' => '保存语言地区']); + //删除语言地区 + Route::delete('lang_country/del/:id', 'v1.setting.LangCountry/langCountryDel')->option(['real_name' => '删除语言地区']); //语言类型列表 Route::get('lang_type/list', 'v1.setting.LangType/langTypeList')->option(['real_name' => '语言类型列表']); //新增修改语言类型表单 diff --git a/crmeb/app/adminapi/route/system.php b/crmeb/app/adminapi/route/system.php index 6ea8afc06..e1f546532 100644 --- a/crmeb/app/adminapi/route/system.php +++ b/crmeb/app/adminapi/route/system.php @@ -94,7 +94,7 @@ Route::group('system', function () { Route::get('upgrade_log/list', 'UpgradeController/upgradeLogList')->option(['real_name' => '升级记录']); //导出备份项目 Route::get('upgrade_export/:id/:type', 'UpgradeController/export')->option(['real_name' => '导出备份']); - + //文件管理登录 Route::post('file/login', 'v1.system.SystemFile/login')->option(['real_name' => '文件管理登录']); })->middleware([ \app\http\middleware\AllowOriginMiddleware::class, @@ -111,9 +111,13 @@ Route::group('system', function () { Route::get('file/openfile', 'v1.system.SystemFile/openfile')->option(['real_name' => '读取文件']); //保存文件 Route::post('file/savefile', 'v1.system.SystemFile/savefile')->option(['real_name' => '保存文件']); + //创建文件夹 Route::get('file/createFolder', 'v1.system.SystemFile/createFolder')->option(['real_name' => '创建文件夹']); + //创建文件 Route::get('file/createFile', 'v1.system.SystemFile/createFile')->option(['real_name' => '创建文件']); + //删除文件夹或者文件 Route::get('file/delFolder', 'v1.system.SystemFile/delFolder')->option(['real_name' => '删除文件夹']); + //重命名文件 Route::get('file/rename', 'v1.system.SystemFile/rename')->option(['real_name' => '重命名文件夹']); })->middleware([ \app\http\middleware\AllowOriginMiddleware::class, diff --git a/crmeb/app/api/controller/v1/PayController.php b/crmeb/app/api/controller/v1/PayController.php index 73b6cccbd..a34042e71 100644 --- a/crmeb/app/api/controller/v1/PayController.php +++ b/crmeb/app/api/controller/v1/PayController.php @@ -38,8 +38,13 @@ class PayController return $pay->handleNotify(); case 'wechat': case 'routine': - /** @var Pay $pay */ - $pay = app()->make(Pay::class); + if (sys_config('pay_wechat_type')) { + /** @var Pay $pay */ + $pay = app()->make(Pay::class, ['v3_wechat_pay']); + } else { + /** @var Pay $pay */ + $pay = app()->make(Pay::class); + } return $pay->handleNotify()->getContent(); } } diff --git a/crmeb/app/api/controller/v1/order/StoreIntegralOrderController.php b/crmeb/app/api/controller/v1/order/StoreIntegralOrderController.php index 4dc5309f8..f19902700 100644 --- a/crmeb/app/api/controller/v1/order/StoreIntegralOrderController.php +++ b/crmeb/app/api/controller/v1/order/StoreIntegralOrderController.php @@ -142,7 +142,7 @@ class StoreIntegralOrderController return app('json')->success([ 'order' => $order, 'express' => [ - 'result' => ['list' => $expressServices->query($cacheName, $order['delivery_id'], $order['delivery_code']) + 'result' => ['list' => $expressServices->query($cacheName, $order['delivery_id'], $order['delivery_code'], $order['user_phone']) ] ] ]); diff --git a/crmeb/app/api/controller/v1/order/StoreOrderController.php b/crmeb/app/api/controller/v1/order/StoreOrderController.php index 1cbc8f429..c7f404b6b 100644 --- a/crmeb/app/api/controller/v1/order/StoreOrderController.php +++ b/crmeb/app/api/controller/v1/order/StoreOrderController.php @@ -409,7 +409,7 @@ class StoreOrderController case 'routine': if ($type == 1 || in_array($order['is_channel'], [0, 2, 3, 4])) { $order['order_id'] = app()->make(StoreOrderCreateServices::class)->getNewOrderId('cp'); - $this->services->update($order['id'],['order_id'=>$order['order_id']],'id'); + $this->services->update($order['id'], ['order_id' => $order['order_id']], 'id'); } break; case 'app': @@ -690,7 +690,7 @@ class StoreOrderController return app('json')->success([ 'order' => $orderInfo, 'express' => [ - 'result' => ['list' => $expressServices->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code']) + 'result' => ['list' => $expressServices->query($cacheName, $orderInfo['delivery_id'], $orderInfo['delivery_code'], $order['user_phone']) ] ] ]); diff --git a/crmeb/app/api/controller/v1/wechat/WechatController.php b/crmeb/app/api/controller/v1/wechat/WechatController.php index 7cb64a9f5..4a72ea99b 100644 --- a/crmeb/app/api/controller/v1/wechat/WechatController.php +++ b/crmeb/app/api/controller/v1/wechat/WechatController.php @@ -51,6 +51,11 @@ class WechatController return $this->services->notify(); } + public function v3notify() + { + return $this->services->v3notify(); + } + /** * 公众号权限配置信息获取 * @param Request $request diff --git a/crmeb/app/api/route/v1.php b/crmeb/app/api/route/v1.php index 69c550084..ddcb8bec2 100644 --- a/crmeb/app/api/route/v1.php +++ b/crmeb/app/api/route/v1.php @@ -15,6 +15,7 @@ use think\Response; Route::any('wechat/serve', 'v1.wechat.WechatController/serve');//公众号服务 Route::any('wechat/notify', 'v1.wechat.WechatController/notify');//公众号支付回调 +Route::any('wechat/v3notify', 'v1.wechat.WechatController/v3notify');//公众号支付回调 Route::any('routine/notify', 'v1.wechat.AuthController/notify');//小程序支付回调 Route::any('pay/notify/:type', 'v1.PayController/notify');//支付回调 Route::get('get_script', 'v1.PublicController/getScript');//获取统计代码 diff --git a/crmeb/app/dao/product/product/StoreProductDao.php b/crmeb/app/dao/product/product/StoreProductDao.php index 6fc4db9df..fd0ade1a7 100644 --- a/crmeb/app/dao/product/product/StoreProductDao.php +++ b/crmeb/app/dao/product/product/StoreProductDao.php @@ -160,7 +160,7 @@ class StoreProductDao extends BaseDao } })->when(!$page && $limit, function ($query) use ($limit) { $query->limit($limit); - })->field($field)->select()->toArray(); + })->order('sort desc')->field($field)->select()->toArray(); } /**商品列表 @@ -225,7 +225,7 @@ class StoreProductDao extends BaseDao ->when($limit, function ($query) use ($limit) { $query->limit($limit); }) - ->order((in_array($field, ['is_hot','is_best']) ? 'sales DESC' : 'sort DESC') . ', id DESC')->select()->toArray(); + ->order(in_array($field, ['is_hot', 'is_best']) ? 'sales DESC,sort DESC, id desc' : 'sort DESC, id desc')->select()->toArray(); } diff --git a/crmeb/app/services/order/StoreOrderRefundServices.php b/crmeb/app/services/order/StoreOrderRefundServices.php index c73860165..d17b0ec70 100644 --- a/crmeb/app/services/order/StoreOrderRefundServices.php +++ b/crmeb/app/services/order/StoreOrderRefundServices.php @@ -188,8 +188,13 @@ class StoreOrderRefundServices extends BaseServices $no = $refundOrder['trade_no']; $refundData['type'] = 'trade_no'; } + if (sys_config('pay_wechat_type')) { + $drivers = 'v3_wechat_pay'; + } else { + $drivers = 'wechat_pay'; + } /** @var Pay $pay */ - $pay = app()->make(Pay::class); + $pay = app()->make(Pay::class, [$drivers]); if ($refundOrder['is_channel'] == 1) { $refundData['trade_no'] = $refundOrder['trade_no']; $refundData['pay_new_weixin_open'] = sys_config('pay_new_weixin_open'); diff --git a/crmeb/app/services/order/StoreOrderServices.php b/crmeb/app/services/order/StoreOrderServices.php index 4a53c7881..d2d5f3fb9 100644 --- a/crmeb/app/services/order/StoreOrderServices.php +++ b/crmeb/app/services/order/StoreOrderServices.php @@ -1581,6 +1581,7 @@ HTML; /** @var UserBillServices $userBillServices */ $userBillServices = app()->make(UserBillServices::class); $data['usable_integral'] = bcsub((string)$user['integral'], (string)$userBillServices->getBillSum(['uid' => $user['uid'], 'is_frozen' => 1]), 0); + $data['integral_open'] = sys_config('integral_ratio', 0) > 0; return $data; } diff --git a/crmeb/app/services/pay/PayServices.php b/crmeb/app/services/pay/PayServices.php index 3d711d6ee..2055ef930 100644 --- a/crmeb/app/services/pay/PayServices.php +++ b/crmeb/app/services/pay/PayServices.php @@ -76,6 +76,10 @@ class PayServices //这些全都是微信支付 if (in_array($payType, ['routine', 'weixinh5', 'weixin', 'pc', 'store'])) { $payType = 'wechat_pay'; + //判断是否使用v3 + if (sys_config('pay_wechat_type') == 1) { + $payType = 'v3_wechat_pay'; + } } if ($payType == 'alipay') { @@ -85,7 +89,7 @@ class PayServices /** @var Pay $pay */ $pay = app()->make(Pay::class, [$payType]); - return $pay->create($orderId, $price, $successAction, $body, '', ['openid' => $openid, 'isCode' => $isCode,'pay_new_weixin_open' => (bool)sys_config('pay_new_weixin_open')]); + return $pay->create($orderId, $price, $successAction, $body, '', ['openid' => $openid, 'isCode' => $isCode, 'pay_new_weixin_open' => (bool)sys_config('pay_new_weixin_open')]); } catch (\Exception $e) { throw new ApiException($e->getMessage()); diff --git a/crmeb/app/services/product/product/StoreProductServices.php b/crmeb/app/services/product/product/StoreProductServices.php index 1ae3761e0..c6fded46d 100644 --- a/crmeb/app/services/product/product/StoreProductServices.php +++ b/crmeb/app/services/product/product/StoreProductServices.php @@ -1954,4 +1954,99 @@ class StoreProductServices extends BaseServices } } + + /** + * 商品批量设置 + * @param $data + * @return bool + * @throws \Exception + */ + public function batchSetting($data) + { + $ids = $data['ids']; + $batchData = []; + if (!count($ids)) throw new AdminException(400337); + switch ($data['type']) { + case 1: // 修改分类 + $cate_id = $data['cate_id']; + if (!count($cate_id)) throw new AdminException(410107); + /** @var StoreCategoryServices $storeCategoryServices */ + $storeCategoryServices = app()->make(StoreCategoryServices::class); + $cateGory = $storeCategoryServices->getColumn([['id', 'IN', $cate_id]], 'id,pid', 'id'); + if (!$cateGory) throw new AdminException(410096); + $time = time(); + $cateData = []; + foreach ($cate_id as $cid) { + if ($cid && isset($cateGory[$cid]['pid'])) { + foreach ($ids as $product_id) { + $cateData[$product_id][] = ['product_id' => $product_id, 'cate_id' => $cid, 'cate_pid' => $cateGory[$cid]['pid'], 'status' => 1, 'add_time' => $time]; + } + } + } + /** @var StoreProductCateServices $storeProductCateServices */ + $storeProductCateServices = app()->make(StoreProductCateServices::class); + foreach ($ids as $product_id) { + $storeProductCateServices->change($product_id, $cateData[$product_id]); + $this->dao->update($product_id, ['cate_id' => implode(',', $cate_id)]); + } + break; + case 2: + foreach ($ids as $product_id) { + $batchData[] = [ + 'id' => $product_id, + 'logistics' => implode(',', $data['logistics']), + 'freight' => $data['freight'], + 'postage' => $data['freight'] == 2 ? $data['postage'] : 0, + 'temp_id' => $data['freight'] == 3 ? $data['temp_id'] : 0 + ]; + } + if (count($batchData)) $this->dao->saveAll($batchData); + break; + case 3: + foreach ($ids as $product_id) { + $batchData[] = [ + 'id' => $product_id, + 'give_integral' => $data['give_integral'] + ]; + } + if (count($batchData)) $this->dao->saveAll($batchData); + break; + case 4: + /** @var StoreProductCouponServices $storeProductCouponServices */ + $storeProductCouponServices = app()->make(StoreProductCouponServices::class); + foreach ($ids as $product_id) { + if (!empty($data['coupon_ids'])) { + $storeProductCouponServices->setCoupon($product_id, $data['coupon_ids']); + } else { + $storeProductCouponServices->delete(['product_id' => $product_id]); + } + } + break; + case 5: + foreach ($ids as $product_id) { + $batchData[] = [ + 'id' => $product_id, + 'label_id' => implode(',', $data['label_id']) + ]; + } + if (count($batchData)) $this->dao->saveAll($batchData); + break; + case 6: + foreach ($ids as $product_id) { + $batchData[] = [ + 'id' => $product_id, + 'is_hot' => in_array('is_hot',$data['recommend']) ? 1 : 0, + 'is_benefit' => in_array('is_benefit',$data['recommend']) ? 1 : 0, + 'is_new' => in_array('is_new',$data['recommend']) ? 1 : 0, + 'is_good' => in_array('is_good',$data['recommend']) ? 1 : 0, + 'is_best' => in_array('is_best',$data['recommend']) ? 1 : 0 + ]; + } + if (count($batchData)) $this->dao->saveAll($batchData); + break; + default: + return true; + } + return true; + } } diff --git a/crmeb/app/services/shipping/ExpressServices.php b/crmeb/app/services/shipping/ExpressServices.php index 14fbf16f6..7910a26b7 100644 --- a/crmeb/app/services/shipping/ExpressServices.php +++ b/crmeb/app/services/shipping/ExpressServices.php @@ -190,7 +190,7 @@ class ExpressServices extends BaseServices * @param string|null $com * @return array */ - public function query(string $cacheName, string $expressNum, string $com = null) + public function query(string $cacheName, string $expressNum, string $com = null, $phone = '') { $resultData = CacheService::get($cacheName, null); if ($resultData === null || !is_array($resultData)) { @@ -200,7 +200,7 @@ class ExpressServices extends BaseServices case 1: /** @var ServeServices $services */ $services = app()->make(ServeServices::class); - $result = $services->express()->query($expressNum, $com); + $result = $services->express()->query($expressNum, $com, $phone); if (isset($result['ischeck']) && $result['ischeck'] == 1) { $cacheTime = 0; } else { diff --git a/crmeb/app/services/system/admin/SystemAdminServices.php b/crmeb/app/services/system/admin/SystemAdminServices.php index b2dd0d08b..aa25e86ca 100644 --- a/crmeb/app/services/system/admin/SystemAdminServices.php +++ b/crmeb/app/services/system/admin/SystemAdminServices.php @@ -138,6 +138,7 @@ class SystemAdminServices extends BaseServices 'id' => $adminInfo->getData('id'), 'account' => $adminInfo->getData('account'), 'head_pic' => $adminInfo->getData('head_pic'), + 'level' => $adminInfo->getData('level'), ], 'logo' => sys_config('site_logo'), 'logo_square' => sys_config('site_logo_square'), @@ -358,6 +359,28 @@ class SystemAdminServices extends BaseServices throw new AdminException(400264); $adminInfo->pwd = $this->passwordHash($data['new_pwd']); } + + $adminInfo->real_name = $data['real_name']; + $adminInfo->head_pic = $data['head_pic']; + if ($adminInfo->save()) + return true; + else + return false; + } + /** + * 设置当前管理员文件管理密码 + * @param int $id + * @param array $data + * @return bool + */ + public function setFilePassword(int $id, array $data) + { + $adminInfo = $this->dao->get($id); + if (!$adminInfo) + throw new AdminException(400451); + if ($adminInfo->is_del) { + throw new AdminException(400452); + } if ($data['file_pwd']) { if ($adminInfo->level != 0) throw new AdminException(400611); if (!$data['conf_file_pwd']) @@ -366,9 +389,6 @@ class SystemAdminServices extends BaseServices throw new AdminException(400264); $adminInfo->file_pwd = $this->passwordHash($data['file_pwd']); } - - $adminInfo->real_name = $data['real_name']; - $adminInfo->head_pic = $data['head_pic']; if ($adminInfo->save()) return true; else diff --git a/crmeb/app/services/system/config/SystemConfigServices.php b/crmeb/app/services/system/config/SystemConfigServices.php index 85656ce8a..9780db058 100644 --- a/crmeb/app/services/system/config/SystemConfigServices.php +++ b/crmeb/app/services/system/config/SystemConfigServices.php @@ -139,7 +139,19 @@ class SystemConfigServices extends BaseServices 'pay_weixin_open' => [ 'son_type' => [ 'pay_weixin_mchid' => '', - 'pay_weixin_key' => '', + 'pay_wechat_type' => [ + 'son_type' => [ + 'pay_weixin_key' => '', + ], + 'show_value' => 0 + ], + 'pay_wechat_type@' => [ + 'son_type' => [ + 'pay_weixin_serial_no' => '', + 'pay_weixin_key_v3' => '' + ], + 'show_value' => 1 + ], 'pay_weixin_client_cert' => '', 'pay_weixin_client_key' => '', 'paydir' => '', diff --git a/crmeb/app/services/system/lang/LangCodeServices.php b/crmeb/app/services/system/lang/LangCodeServices.php index 10ed556d2..4812cb2ab 100644 --- a/crmeb/app/services/system/lang/LangCodeServices.php +++ b/crmeb/app/services/system/lang/LangCodeServices.php @@ -34,8 +34,8 @@ class LangCodeServices extends BaseServices $typeList = $langTypeServices->getColumn([['status', '=', 1], ['is_del', '=', 0]], 'language_name,file_name,id', 'id'); $langType = [ 'isAdmin' => [ - ['title' => '用户端', 'value' => 0], - ['title' => '管理端', 'value' => 1] + ['title' => '用户端页面', 'value' => 0], + ['title' => '后端接口', 'value' => 1] ] ]; foreach ($typeList as $value) { diff --git a/crmeb/app/services/system/lang/LangCountryServices.php b/crmeb/app/services/system/lang/LangCountryServices.php index 1cfece08c..9072af1d2 100644 --- a/crmeb/app/services/system/lang/LangCountryServices.php +++ b/crmeb/app/services/system/lang/LangCountryServices.php @@ -19,7 +19,7 @@ class LangCountryServices extends BaseServices } /** - * 国家语言列表 + * 地区语言列表 * @param array $where * @return array * @throws \think\db\exception\DataNotFoundException @@ -35,7 +35,7 @@ class LangCountryServices extends BaseServices } /** - * 设置国家语言类型表单 + * 添加语言地区表单 * @param $id * @return array * @throws \FormBuilder\Exception\FormBuilderException @@ -43,32 +43,41 @@ class LangCountryServices extends BaseServices * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ - public function LangCountryTypeForm($id) + public function langCountryForm($id) { - if (!$id) throw new AdminException(100100); - $info = $this->dao->get($id); - if (!$info) throw new AdminException(100026); - /** @var LangTypeServices $typeServices */ - $typeServices = app()->make(LangTypeServices::class); - $typeList = $typeServices->getColumn(['status' => 1, 'is_del' => 0], 'language_name,file_name', 'id'); - $options[] = ['value' => 0, 'label' => '未定义']; - foreach ($typeList as $item) { - $options[] = ['value' => $item['id'], 'label' => $item['language_name'] . '(' . $item['file_name'] . ')']; - } - $field[] = Form::select('type', '选择语言类型', $info->type_id)->setOptions($options)->filterable(1); - return create_form('设置语言类型', $field, Url::buildUrl('/setting/lang_country/save/' . $id), 'POST'); + if ($id) $info = $this->dao->get($id); + $field = []; + $field[] = Form::input('name', '所属地区', $info['name'] ?? '')->required('请填写所属地区'); + $field[] = Form::input('code', '语言码', $info['code'] ?? '')->required('请填写语言码'); + return create_form($id ? '修改语言地区' : '新增语言地区', $field, Url::buildUrl('/setting/lang_country/save/' . $id), 'POST'); } /** - * 国家语言修改 + * 保存语言地区 * @param $id * @param $typeId * @return bool */ - public function LangCountrySave($id, $typeId) + public function LangCountrySave($id, $data) { - $res = $this->dao->update(['id' => $id], ['type_id' => $typeId]); + if ($id) { + $res = $this->dao->update(['id' => $id], $data); + } else { + $res = $this->dao->save($data); + } if (!$res) throw new AdminException(100007); return true; } + + /** + * 删除语言地区 + * @param $id + * @return bool + */ + public function langCountryDel($id) + { + $res = $this->dao->delete($id); + if (!$res) throw new AdminException(100008); + return true; + } } \ No newline at end of file diff --git a/crmeb/app/services/wechat/WechatServices.php b/crmeb/app/services/wechat/WechatServices.php index dd5e170c1..cdca6767c 100644 --- a/crmeb/app/services/wechat/WechatServices.php +++ b/crmeb/app/services/wechat/WechatServices.php @@ -21,6 +21,7 @@ use crmeb\services\CacheService; use crmeb\services\CacheService as Cache; use crmeb\services\app\WechatService as WechatAuthService; use crmeb\services\oauth\OAuth; +use crmeb\services\pay\Pay; use crmeb\utils\Canvas; /** @@ -60,6 +61,21 @@ class WechatServices extends BaseServices return WechatAuthService::handleNotify()->getContent(); } + /** + * v3支付回调 + * @return string + * @throws \EasyWeChat\Core\Exceptions\FaultException + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function v3notify() + { + /** @var Pay $pay */ + $pay = app()->make(Pay::class, ['v3_wechat_pay']); + return $pay->handleNotify()->getContent(); + } + /** * 公众号权限配置信息获取 * @param $url diff --git a/crmeb/crmeb/services/app/WechatService.php b/crmeb/crmeb/services/app/WechatService.php index af6f1e241..b0b5331b6 100644 --- a/crmeb/crmeb/services/app/WechatService.php +++ b/crmeb/crmeb/services/app/WechatService.php @@ -146,9 +146,9 @@ class WechatService $response = $messageService->wechatEventView($message); break; case 'funds_order_pay': - $prefix = substr($message['order_info']['trade_no'],0,2); + $prefix = substr($message['order_info']['trade_no'], 0, 2); //处理一下参数 - switch ($prefix){ + switch ($prefix) { case 'cp': $data['attach'] = 'Product'; break; @@ -162,14 +162,12 @@ class WechatService $data['out_trade_no'] = $message['order_info']['trade_no']; $data['transaction_id'] = $message['order_info']['transaction_id']; $data['opneid'] = $message['FromUserName']; - if(Event::until('pay.notify', [$data])) - { + if (Event::until('pay.notify', [$data])) { $response = 'success'; - }else - { + } else { $response = 'faild'; } - Log::error(['data'=>$data,'res'=>$response,'message'=>$message]); + Log::error(['data' => $data, 'res' => $response, 'message' => $message]); break; } break; @@ -446,6 +444,7 @@ class WechatService } } } + /** * 获得下单ID 新小程序支付 * @param $openid @@ -500,6 +499,7 @@ class WechatService $paymentPrepare = self::paymentPrepare($openid, $out_trade_no, $total_fee, $attach, $body, $detail, $trade_type, $options); return self::paymentService()->configForJSSDKPayment($paymentPrepare->prepay_id); } + /** * 获得jsSdk支付参数 新小程序支付 * @param $openid diff --git a/crmeb/crmeb/services/easywechat/Application.php b/crmeb/crmeb/services/easywechat/Application.php index 5ef51091c..3e776f626 100644 --- a/crmeb/crmeb/services/easywechat/Application.php +++ b/crmeb/crmeb/services/easywechat/Application.php @@ -14,7 +14,10 @@ namespace crmeb\services\easywechat; use crmeb\services\easywechat\miniPayment\ServiceProvider; use crmeb\services\easywechat\oauth2\wechat\WechatOauth2Provider; +use crmeb\services\easywechat\subscribe\ProgramProvider; +use crmeb\services\easywechat\v3pay\PayClient; use crmeb\services\easywechat\wechatlive\ProgramProvider as LiveProgramProvider; +use crmeb\services\easywechat\v3pay\ServiceProvider as V3PayServiceProvider; /** @@ -22,6 +25,7 @@ use crmeb\services\easywechat\wechatlive\ProgramProvider as LiveProgramProvider; * @package crmeb\services\easywechat * @property LiveProgramProvider $wechat_live * @property WechatOauth2Provider $oauth2 + * @property PayClient $v3pay */ class Application extends \EasyWeChat\Foundation\Application { @@ -32,7 +36,10 @@ class Application extends \EasyWeChat\Foundation\Application protected $providersNew = [ LiveProgramProvider::class, WechatOauth2Provider::class, - ServiceProvider::class + ServiceProvider::class, + ProgramProvider::class, + V3PayServiceProvider::class, + \crmeb\services\easywechat\Open3rd\ProgramProvider::class, ]; /** diff --git a/crmeb/crmeb/services/easywechat/miniPayment/WeChatClient.php b/crmeb/crmeb/services/easywechat/miniPayment/WeChatClient.php index 4bfeda084..1605b7567 100644 --- a/crmeb/crmeb/services/easywechat/miniPayment/WeChatClient.php +++ b/crmeb/crmeb/services/easywechat/miniPayment/WeChatClient.php @@ -49,7 +49,7 @@ class WeChatClient extends AbstractAPI /** * 支付 - * @param array $params[ + * @param array $params [ * 'openid'=>'支付者的openid', * 'out_trade_no'=>'商家合单支付总交易单号', * 'total_fee'=>'支付金额', @@ -64,15 +64,15 @@ class WeChatClient extends AbstractAPI public function createorder($order) { $params = [ - 'openid'=>$order['openid'], // 支付者的openid - 'combine_trade_no'=>$order['out_trade_no'], // 商家合单支付总交易单号 - 'expire_time'=>time()+$this->expire_time, - 'sub_orders'=>[ + 'openid' => $order['openid'], // 支付者的openid + 'combine_trade_no' => $order['out_trade_no'], // 商家合单支付总交易单号 + 'expire_time' => time() + $this->expire_time, + 'sub_orders' => [ [ - 'mchid'=>$this->merchant->merchant_id, - 'amount'=>(int)$order['total_fee'], - 'trade_no'=>$order['out_trade_no'], - 'description'=>$order['body'] + 'mchid' => $this->merchant->merchant_id, + 'amount' => (int)$order['total_fee'], + 'trade_no' => $order['out_trade_no'], + 'description' => $order['body'] ] ] ]; @@ -81,7 +81,7 @@ class WeChatClient extends AbstractAPI /** * 退款 - * @param array $params[ + * @param array $params [ * 'openid'=>'退款者的openid', * 'trade_no'=>'商家交易单号', * 'transaction_id'=>'支付单号', @@ -95,13 +95,13 @@ class WeChatClient extends AbstractAPI public function refundorder(array $order) { $params = [ - 'openid'=>$order['openid'], - 'mchid'=>$this->merchant->merchant_id, - 'trade_no'=>$order['trade_no'], - 'transaction_id'=>$order['transaction_id'], - 'refund_no'=>$order['refund_no'], - 'total_amount'=>$order['total_amount'], - 'refund_amount'=>$order['refund_amount'], + 'openid' => $order['openid'], + 'mchid' => $this->merchant->merchant_id, + 'trade_no' => $order['trade_no'], + 'transaction_id' => $order['transaction_id'], + 'refund_no' => $order['refund_no'], + 'total_amount' => $order['total_amount'], + 'refund_amount' => $order['refund_amount'], ]; return $this->parseJSON('post', [self::API_SET_REFUND_ORDER, json_encode($params)]); } diff --git a/crmeb/crmeb/services/easywechat/v3pay/BaseClient.php b/crmeb/crmeb/services/easywechat/v3pay/BaseClient.php new file mode 100644 index 000000000..986330ad4 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/v3pay/BaseClient.php @@ -0,0 +1,280 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use crmeb\exceptions\PayException; +use crmeb\services\easywechat\Application; +use EasyWeChat\Core\AbstractAPI; +use EasyWeChat\Core\AccessToken; +use EasyWeChat\Core\Exceptions\HttpException; +use EasyWeChat\Core\Exceptions\InvalidConfigException; +use EasyWeChat\Core\Http; +use EasyWeChat\Encryption\EncryptionException; +use think\exception\InvalidArgumentException; + + +class BaseClient extends AbstractAPI +{ + + use Certficates; + + /** + * @var Application + */ + protected $app; + + const BASE_URL = 'https://api.mch.weixin.qq.com/'; + + const KEY_LENGTH_BYTE = 32; + + const AUTH_TAG_LENGTH_BYTE = 16; + + /** + * BaseClient constructor. + * @param AccessToken $accessToken + * @param $app + */ + public function __construct(AccessToken $accessToken, $app) + { + parent::__construct($accessToken); + $this->app = $app; + } + + /** + * request. + * + * @param string $endpoint + * @param string $method + * @param array $options + * @param bool $returnResponse + */ + public function request(string $endpoint, string $method = 'POST', array $options = [], $serial = true) + { + $body = $options['body'] ?? ''; + + if (isset($options['json'])) { + $body = json_encode($options['json']); + $options['body'] = $body; + unset($options['json']); + } + + $headers = [ + 'Content-Type' => 'application/json', + 'User-Agent' => 'curl', + 'Accept' => 'application/json', + 'Authorization' => $this->getAuthorization($endpoint, $method, $body), + ]; + + $options['headers'] = array_merge($headers, ($options['headers'] ?? [])); + + if ($serial) { + $options['headers']['Wechatpay-Serial'] = $this->getCertficatescAttr('serial_no'); + } + + return $this->_doRequestCurl($method, self::BASE_URL . $endpoint, $options); + } + + /** + * @param $method + * @param $location + * @param array $options + * @return mixed + */ + private function _doRequestCurl($method, $location, $options = []) + { + $curl = curl_init(); + // POST数据设置 + if (strtolower($method) === 'post') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $options['data'] ?? $options['body'] ?? ''); + } + // CURL头信息设置 + if (!empty($options['headers'])) { + $headers = []; + foreach ($options['headers'] as $k => $v) { + $headers[] = "$k: $v"; + } + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + } + curl_setopt($curl, CURLOPT_URL, $location); + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 60); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + $content = curl_exec($curl); + $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + curl_close($curl); + return json_decode(substr($content, $headerSize), true); + } + + /** + * To id card, mobile phone number and other fields sensitive information encryption. + * + * @param string $string + * + * @return string + */ + protected function encryptSensitiveInformation(string $string) + { + $certificates = $this->app->certficates->get()['certificates']; + if (null === $certificates) { + throw new InvalidConfigException('config certificate connot be empty.'); + } + $encrypted = ''; + if (openssl_public_encrypt($string, $encrypted, $certificates, OPENSSL_PKCS1_OAEP_PADDING)) { + //base64编码 + $sign = base64_encode($encrypted); + } else { + throw new EncryptionException('Encryption of sensitive information failed'); + } + return $sign; + } + + + /** + * @param string $url + * @param string $method + * @param string $body + * @return string + */ + protected function getAuthorization(string $url, string $method, string $body) + { + $nonceStr = uniqid(); + $timestamp = time(); + $message = $method . "\n" . + '/' . $url . "\n" . + $timestamp . "\n" . + $nonceStr . "\n" . + $body . "\n"; + openssl_sign($message, $raw_sign, $this->getPrivateKey(), 'sha256WithRSAEncryption'); + $sign = base64_encode($raw_sign); + $schema = 'WECHATPAY2-SHA256-RSA2048 '; + $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', + $this->app['config']['v3_payment']['mchid'], $nonceStr, $timestamp, $this->app['config']['v3_payment']['serial_no'], $sign); + return $schema . $token; + } + + /** + * 获取商户私钥 + * @return bool|resource + */ + protected function getPrivateKey() + { + $key_path = $this->app['config']['v3_payment']['key_path']; + if (!file_exists($key_path)) { + throw new \InvalidArgumentException( + "SSL certificate not found: {$key_path}" + ); + } + return openssl_pkey_get_private(file_get_contents($key_path)); + } + + /** + * 获取商户公钥 + * @return bool|resource + */ + protected function getPublicKey() + { + $key_path = $this->app['config']['v3_payment']['cert_path']; + if (!file_exists($key_path)) { + throw new \InvalidArgumentException( + "SSL certificate not found: {$key_path}" + ); + } + return openssl_pkey_get_public(file_get_contents($key_path)); + } + + /** + * 替换url + * @param string $url + * @param $search + * @param $replace + * @return array|string|string[] + */ + public function getApiUrl(string $url, $search, $replace) + { + $newSearch = []; + foreach ($search as $key) { + $newSearch[] = '{' . $key . '}'; + } + return str_replace($newSearch, $replace, $url); + } + + /** + * @param int $padding + */ + private static function paddingModeLimitedCheck(int $padding): void + { + if (!($padding === OPENSSL_PKCS1_OAEP_PADDING || $padding === OPENSSL_PKCS1_PADDING)) { + throw new PayException(sprintf("Doesn't supported padding mode(%d), here only support OPENSSL_PKCS1_OAEP_PADDING or OPENSSL_PKCS1_PADDING.", $padding)); + } + } + + /** + * 加密数据 + * @param string $plaintext + * @param int $padding + * @return string + */ + public function encryptor(string $plaintext, int $padding = OPENSSL_PKCS1_OAEP_PADDING) + { + self::paddingModeLimitedCheck($padding); + + if (!openssl_public_encrypt($plaintext, $encrypted, $this->getPublicKey(), $padding)) { + throw new PayException('Encrypting the input $plaintext failed, please checking your $publicKey whether or nor correct.'); + } + + return base64_encode($encrypted); + } + + /** + * decrypt ciphertext. + * + * @param array $encryptCertificate + * + * @return string + */ + public function decrypt(array $encryptCertificate) + { + $ciphertext = base64_decode($encryptCertificate['ciphertext'], true); + $associatedData = $encryptCertificate['associated_data']; + $nonceStr = $encryptCertificate['nonce']; + $aesKey = $this->app['config']['v3_payment']['key']; + + try { + // ext-sodium (default installed on >= PHP 7.2) + if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) { + return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey); + } + // ext-libsodium (need install libsodium-php 1.x via pecl) + if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') && \Sodium\crypto_aead_aes256gcm_is_available()) { + return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey); + } + // openssl (PHP >= 7.1 support AEAD) + if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) { + $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE); + $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE); + return \openssl_decrypt($ctext, 'aes-256-gcm', $aesKey, \OPENSSL_RAW_DATA, $nonceStr, $authTag, $associatedData); + } + } catch (\Exception $exception) { + throw new InvalidArgumentException($exception->getMessage(), $exception->getCode()); + } catch (\SodiumException $exception) { + throw new InvalidArgumentException($exception->getMessage(), $exception->getCode()); + } + throw new InvalidArgumentException('AEAD_AES_256_GCM 需要 PHP 7.1 以上或者安装 libsodium-php'); + } +} + diff --git a/crmeb/crmeb/services/easywechat/v3pay/Certficates.php b/crmeb/crmeb/services/easywechat/v3pay/Certficates.php new file mode 100644 index 000000000..b4dc65ba2 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/v3pay/Certficates.php @@ -0,0 +1,68 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use crmeb\exceptions\PayException; +use think\facade\Cache; + +/** + * Class Certficates + * @package crmeb\services\easywechat\v3pay + */ +trait Certficates +{ + + /** + * @param string|null $key + * @return array|mixed|null + * @throws \Psr\SimpleCache\InvalidArgumentException + */ + public function getCertficatescAttr(string $key = null) + { + $driver = Cache::store('file'); + $cacheKey = '_wx_v3' . $this->app['config']['v3_payment']['serial_no']; + if ($driver->has($cacheKey)) { + $res = $driver->get($cacheKey); + if ($key && $res) { + return $res[$key] ?? null; + } else { + return $res; + } + } + $certficates = $this->getCertficates(); + $driver->set($cacheKey, $certficates, 3600 * 24 * 30); + if ($key && $certficates) { + return $certficates[$key] ?? null; + } + return $certficates; + } + + /** + * get certficates. + * + * @return array + */ + public function getCertficates() + { + $response = $this->request('v3/certificates', 'GET', [], false); + if (isset($response['code'])) { + throw new PayException($response['message']); + } + $certificates = $response['data'][0]; + $certificates['certificates'] = $this->decrypt($certificates['encrypt_certificate']); + unset($certificates['encrypt_certificate']); + return $certificates; + } +} diff --git a/crmeb/crmeb/services/easywechat/v3pay/PayClient.php b/crmeb/crmeb/services/easywechat/v3pay/PayClient.php new file mode 100644 index 000000000..b665b94e9 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/v3pay/PayClient.php @@ -0,0 +1,400 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use crmeb\exceptions\PayException; + +/** + * v3支付 + * Class PayClient + * @package crmeb\services\easywechat\v3pay + */ +class PayClient extends BaseClient +{ + //app支付 + const API_APP_APY_URL = 'v3/pay/transactions/app'; + //二维码支付截图 + const API_NATIVE_URL = 'v3/pay/transactions/native'; + //h5支付接口 + const API_H5_URL = 'v3/pay/transactions/h5'; + //jsapi支付接口 + const API_JSAPI_URL = 'v3/pay/transactions/jsapi'; + //发起商家转账API + const API_BATCHES_URL = 'v3/transfer/batches'; + //退款 + const API_REFUND_URL = 'v3/refund/domestic/refunds'; + //退款查询接口 + const API_REFUND_QUERY_URL = 'v3/refund/domestic/refunds/{out_refund_no}'; + + /** + * 公众号jsapi支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function jsapiPay(string $openid, string $outTradeNo, string $total, string $description, string $attach) + { + $appId = $this->app['config']['wechat']['appid']; + $res = $this->pay('jsapi', $appId, $outTradeNo, $total, $description, $attach, ['openid' => $openid]); + return $this->configForJSSDKPayment($appId, $res['prepay_id']); + } + + /** + * 小程序支付 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return array|false|string + */ + public function miniprogPay(string $openid, string $outTradeNo, string $total, string $description, string $attach) + { + $appId = $this->app['config']['miniprog']['appid']; + $res = $this->pay('jsapi', $appId, $outTradeNo, $total, $description, $attach, ['openid' => $openid]); + return $this->configForJSSDKPayment($appId, $res['prepay_id']); + } + + /** + * APP支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function appPay(string $outTradeNo, string $total, string $description, string $attach) + { + $res = $this->pay('app', $this->app['config']['app']['appid'], $outTradeNo, $total, $description, $attach); + return $this->configForAppPayment($res['prepay_id']); + } + + /** + * native支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function nativePay(string $outTradeNo, string $total, string $description, string $attach) + { + return $this->pay('native', $this->app['config']['web']['appid'], $outTradeNo, $total, $description, $attach); + } + + /** + * h5支付下单 + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @return mixed + */ + public function h5Pay(string $outTradeNo, string $total, string $description, string $attach) + { + return $this->pay('h5', $this->app['config']['wechat']['appid'], $outTradeNo, $total, $description, $attach); + } + + /** + * 下单 + * @param string $type + * @param string $appid + * @param string $outTradeNo + * @param string $total + * @param string $description + * @param string $attach + * @param array $payer + * @return mixed + */ + public function pay(string $type, string $appid, string $outTradeNo, string $total, string $description, string $attach, array $payer = []) + { + $totalFee = (int)bcmul($total, '100'); + + $data = [ + 'appid' => $appid, + 'mchid' => $this->app['config']['v3_payment']['mchid'], + 'out_trade_no' => $outTradeNo, + 'attach' => $attach, + 'description' => $description, + 'notify_url' => $this->app['config']['v3_payment']['notify_url'], + 'amount' => [ + 'total' => $totalFee, + 'currency' => 'CNY' + ], + ]; + + if ($payer) { + $data['payer'] = $payer; + } + + $url = ''; + switch ($type) { + case 'h5': + $url = self::API_H5_URL; + $data['scene_info'] = [ + 'payer_client_ip' => request()->ip(), + 'h5_info' => [ + 'type' => 'Wap' + ] + ]; + break; + case 'native': + $url = self::API_NATIVE_URL; + break; + case 'app': + $url = self::API_APP_APY_URL; + break; + case 'jsapi': + $url = self::API_JSAPI_URL; + break; + } + + if (!$url) { + throw new PayException('缺少请求地址'); + } + + $res = $this->request($url, 'POST', ['json' => $data]); + + if (!$res) { + throw new PayException('微信支付:下单失败'); + } + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + } + + /** + * 发起商家转账API + * @param string $outBatchNo + * @param string $amount + * @param string $batchName + * @param string $remark + * @param array $transferDetailList + * @return mixed + */ + public function batches(string $outBatchNo, string $amount, string $batchName, string $remark, array $transferDetailList) + { + $totalFee = '0'; + + foreach ($transferDetailList as &$item) { + if ($item['transfer_amount'] >= 2000 && !empty($item['user_name'])) { + throw new PayException('明细金额大于等于2000时,收款人姓名必须填写'); + } + $totalFee = bcadd($totalFee, $item['transfer_amount'], 2); + $item['transfer_amount'] = (int)bcmul($item['transfer_amount'], 100, 0); + if (isset($item['user_name'])) { + $item['user_name'] = $this->encryptor($item['user_name']); + } + } + + if ($totalFee !== $amount) { + throw new PayException('转账明细金额总和和转账总金额不一致'); + } + + $amount = (int)bcmul($amount, 100, 0); + + $data = [ + 'appid' => $this->app['config']['wechat']['appid'], + 'out_batch_no' => $outBatchNo, + 'batch_name' => $batchName, + 'batch_remark' => $remark, + 'total_amount' => $amount, + 'total_num' => count($transferDetailList), + 'transfer_detail_list' => $transferDetailList + ]; + + $res = $this->request(self::API_BATCHES_URL, 'POST', ['json' => $data]); + + if (!$res) { + throw new PayException('微信支付:发起商家转账失败'); + } + + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + + } + + /** + * 退款 + * @param string $outTradeNo + * @param array $options + * @return mixed + */ + public function refund(string $outTradeNo, array $options = []) + { + if (!isset($options['pay_price'])) { + throw new PayException(400730); + } + $totalFee = floatval(bcmul($options['pay_price'], 100, 0)); + $refundFee = isset($options['refund_price']) ? floatval(bcmul($options['refund_price'], 100, 0)) : null; + $refundReason = $options['desc'] ?? ''; + $refundNo = $options['refund_id'] ?? $outTradeNo; + /*仅针对老资金流商户使用 + REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款) + REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款 + */ + $refundAccount = $opt['refund_account'] ?? 'AVAILABLE'; + + $data = [ + 'transaction_id' => $outTradeNo, + 'out_refund_no' => $refundNo, + 'amount' => [ + 'refund' => (int)$refundFee, + 'currency' => 'CNY', + 'total' => (int)$totalFee + ], + 'funds_account' => $refundAccount + ]; + + if ($refundReason) { + $data['reason'] = $refundReason; + } + + $res = $this->request(self::API_REFUND_URL, 'POST', ['json' => $data]); + + if (!$res) { + throw new PayException('微信支付:发起退款失败'); + } + + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + } + + /** + * 查询退款 + * @param string $outRefundNo + * @return mixed + */ + public function queryRefund(string $outRefundNo) + { + $res = $this->request($this->getApiUrl(self::API_REFUND_QUERY_URL, ['out_refund_no'], [$outRefundNo]), 'GET'); + + if (!$res) { + throw new PayException(50001); + } + + if (isset($res['code']) && isset($res['message'])) { + throw new PayException($res['message']); + } + + return $res; + } + + /** + * jsapi支付 + * @param string $appid + * @param string $prepayId + * @param bool $json + * @return array|false|string + */ + public function configForPayment(string $appid, string $prepayId, bool $json = true) + { + $params = [ + 'appId' => $appid, + 'timeStamp' => strval(time()), + 'nonceStr' => uniqid(), + 'package' => "prepay_id=$prepayId", + 'signType' => 'RSA', + ]; + $message = $params['appId'] . "\n" . + $params['timeStamp'] . "\n" . + $params['nonceStr'] . "\n" . + $params['package'] . "\n"; + openssl_sign($message, $raw_sign, $this->getPrivateKey(), 'sha256WithRSAEncryption'); + $sign = base64_encode($raw_sign); + + $params['paySign'] = $sign; + + return $json ? json_encode($params) : $params; + } + + /** + * Generate app payment parameters. + * @param string $prepayId + * @return array + */ + public function configForAppPayment(string $prepayId): array + { + $params = [ + 'appid' => $this->app['config']['app']['appid'], + 'partnerid' => $this->app['config']['v3_payment']['mchid'], + 'prepayid' => $prepayId, + 'noncestr' => uniqid(), + 'timestamp' => time(), + 'package' => 'Sign=WXPay', + ]; + $message = $params['appid'] . "\n" . + $params['timestamp'] . "\n" . + $params['noncestr'] . "\n" . + $params['prepayid'] . "\n"; + openssl_sign($message, $raw_sign, $this->getPrivateKey(), 'sha256WithRSAEncryption'); + $sign = base64_encode($raw_sign); + + $params['sign'] = $sign; + + return $params; + } + + /** + * 小程序支付 + * @param string $appid + * @param string $prepayId + * @return array|false|string + */ + public function configForJSSDKPayment(string $appid, string $prepayId) + { + $config = $this->configForPayment($appid, $prepayId, false); + + $config['timestamp'] = $config['timeStamp']; + unset($config['timeStamp']); + + return $config; + } + + /** + * @param $callback + * @return \think\Response + */ + public function handleNotify($callback) + { + $request = request(); + $success = $request->post('event_type') === 'TRANSACTION.SUCCESS'; + $data = $this->decrypt($request->post('resource', [])); + + $handleResult = call_user_func_array($callback, [json_decode($data), $success]); + if (is_bool($handleResult) && $handleResult) { + $response = [ + 'code' => 'SUCCESS', + 'message' => 'OK', + ]; + } else { + $response = [ + 'code' => 'FAIL', + 'message' => $handleResult, + ]; + } + + return response($response, 200, [], 'json'); + } +} diff --git a/crmeb/crmeb/services/easywechat/v3pay/ServiceProvider.php b/crmeb/crmeb/services/easywechat/v3pay/ServiceProvider.php new file mode 100644 index 000000000..efd32f291 --- /dev/null +++ b/crmeb/crmeb/services/easywechat/v3pay/ServiceProvider.php @@ -0,0 +1,36 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\easywechat\v3pay; + + +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * Class ServiceProvider + * @package crmeb\services\easywechat\v3pay + */ +class ServiceProvider implements ServiceProviderInterface +{ + + /** + * @param Container $pimple + */ + public function register(Container $pimple) + { + $pimple['v3pay'] = function ($pimple) { + return new PayClient($pimple['access_token'], $pimple); + }; + } +} diff --git a/crmeb/crmeb/services/express/storage/Express.php b/crmeb/crmeb/services/express/storage/Express.php index aef3a97bb..ac00819af 100644 --- a/crmeb/crmeb/services/express/storage/Express.php +++ b/crmeb/crmeb/services/express/storage/Express.php @@ -110,11 +110,12 @@ class Express extends BaseExpress * @return 物流状态:status 0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转单,10待清关,11清关中,12已清关,13清关异常,14收件人拒签 * @return 物流详情 content */ - public function query(string $num, string $com = '') + public function query(string $num, string $com = '', $phone = '') { $param = [ 'com' => $com, - 'num' => $num + 'num' => $num, + 'phone' => $phone ]; if ($com === null) { unset($param['com']); @@ -156,7 +157,7 @@ class Express extends BaseExpress } /** @var ExpressServices $expressServices */ $expressServices = app()->make(ExpressServices::class); - $expressData = $expressServices->getOneByWhere(['code'=>$param['com']])->toArray(); + $expressData = $expressServices->getOneByWhere(['code' => $param['com']])->toArray(); if (isset($data['cargo'])) $param['cargo'] = $data['cargo']; if ($expressData['partner_id'] == 1) $param['partner_id'] = $expressData['account']; if ($expressData['partner_key'] == 1) $param['partner_key'] = $expressData['key']; diff --git a/crmeb/crmeb/services/pay/Pay.php b/crmeb/crmeb/services/pay/Pay.php index 17017340d..c90381a15 100644 --- a/crmeb/crmeb/services/pay/Pay.php +++ b/crmeb/crmeb/services/pay/Pay.php @@ -14,6 +14,7 @@ namespace crmeb\services\pay; use crmeb\basic\BaseManager; use crmeb\services\pay\storage\AliPay; +use crmeb\services\pay\storage\V3WechatPay; use crmeb\services\pay\storage\WechatPay; use think\facade\Config; @@ -23,6 +24,7 @@ use think\facade\Config; * @package crmeb\services\pay * @mixin AliPay * @mixin WechatPay + * @mixin V3WechatPay */ class Pay extends BaseManager { diff --git a/crmeb/crmeb/services/pay/PayInterface.php b/crmeb/crmeb/services/pay/PayInterface.php index 4bb4f9368..6fd65f6b9 100644 --- a/crmeb/crmeb/services/pay/PayInterface.php +++ b/crmeb/crmeb/services/pay/PayInterface.php @@ -72,6 +72,6 @@ interface PayInterface * 支付回调 * @return mixed */ - public static function handleNotify(); + public function handleNotify(); } diff --git a/crmeb/crmeb/services/pay/storage/V3WechatPay.php b/crmeb/crmeb/services/pay/storage/V3WechatPay.php new file mode 100644 index 000000000..3d37f9031 --- /dev/null +++ b/crmeb/crmeb/services/pay/storage/V3WechatPay.php @@ -0,0 +1,216 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\services\pay\storage; + +use app\services\pay\PayNotifyServices; +use app\services\wechat\WechatMessageServices; +use crmeb\exceptions\PayException; +use crmeb\services\app\MiniProgramService; +use crmeb\services\easywechat\Application; +use crmeb\services\pay\BasePay; +use crmeb\services\pay\PayInterface; +use crmeb\utils\Hook; +use EasyWeChat\Payment\Order; +use think\facade\Log; + +/** + * Class 微信支付v3 + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + * @package crmeb\services\pay\storage + */ +class V3WechatPay extends BasePay implements PayInterface +{ + + /** + * @var Application + */ + protected $instance; + + /** + * @param array $config + * @return mixed|void + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + protected function initialize(array $config = []) + { + $wechatAppid = sys_config('wechat_appid'); + $config = [ + 'app' => [ + 'appid' => sys_config('wechat_app_appid'), + ], + 'wechat' => [ + 'appid' => $wechatAppid, + ], + 'miniprog' => [ + 'appid' => sys_config('routine_appId'), + ], + 'web' => [ + 'appid' => sys_config('wechat_open_app_id', $wechatAppid), + ], + 'v3_payment' => [ + 'mchid' => sys_config('pay_weixin_mchid'), + 'key' => sys_config('pay_weixin_key_v3'), + 'serial_no' => sys_config('pay_weixin_serial_no'), + 'cert_path' => public_path() . $this->getPemPath(sys_config('pay_weixin_client_cert')), + 'key_path' => public_path() . $this->getPemPath(sys_config('pay_weixin_client_key')), + 'notify_url' => trim(sys_config('site_url')) . '/api/wechat/v3notify', + ] + ]; + $this->instance = new Application($config); + } + + /** + * 获取证书不带域名的路径 + * @param string $path + * @return mixed|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function getPemPath(string $path) + { + if (strstr($path, 'http://') === false && strstr($path, 'https://') === false) { + return $path; + } else { + $res = parse_url($path); + return $res['path'] ?? ''; + } + } + + /** + * 创建订单返回支付参数 + * @param string $orderId + * @param string $totalFee + * @param string $attach + * @param string $body + * @param string $detail + * @param array $options + * @return array|false|mixed|string + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function create(string $orderId, string $totalFee, string $attach, string $body, string $detail, array $options = []) + { + $this->authSetPayType(); + + switch ($this->payType) { + case Order::NATIVE: + $res = $this->instance->v3pay->nativePay($orderId, $totalFee, $body, $attach); + $res['invalid'] = time() + 60; + $res['logo'] = sys_config('wap_login_logo'); + return $res; + case Order::APP: + return $this->instance->v3pay->appPay($orderId, $totalFee, $body, $attach); + case Order::JSAPI: + if (empty($options['openid'])) { + throw new PayException('缺少openid'); + } + if (request()->isRoutine()) { + // 获取配置 判断是否为新支付 + if ($options['pay_new_weixin_open']) { + return MiniProgramService::newJsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail, $options); + } + return $this->instance->v3pay->miniprogPay($options['openid'], $orderId, $totalFee, $body, $attach); + } + return $this->instance->v3pay->jsapiPay($options['openid'], $orderId, $totalFee, $body, $attach); + case 'h5': + return $this->instance->v3pay->h5Pay($orderId, $totalFee, $body, $attach); + default: + throw new PayException('微信支付:支付类型错误'); + } + } + + /** + * @param string $openid + * @param string $orderId + * @param string $amount + * @param array $options + * @return mixed + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function merchantPay(string $openid, string $orderId, string $amount, array $options = []) + { + $res = $this->instance->v3pay->batches( + $orderId, + $amount, + $options['batch_name'], + $options['batch_remark'], + [ + [ + 'out_detail_no' => $orderId, + 'transfer_amount' => $amount, + 'transfer_remark' => $options['batch_remark'], + 'openid' => $openid + ] + ] + ); + + return $res; + } + + /** + * 发起退款 + * @param string $outTradeNo + * @param array $options + * @return mixed + */ + public function refund(string $outTradeNo, array $options = []) + { + return $this->instance->v3pay->refund($outTradeNo, $options); + } + + /** + * 查询退款 + * @param string $outTradeNo + * @param string|null $outRequestNo + * @param array $other + * @return mixed + */ + public function queryRefund(string $outTradeNo, string $outRequestNo = null, array $other = []) + { + return $this->instance->v3pay->queryRefund($outTradeNo); + } + + /** + * @return mixed|\think\Response + * @author 等风来 + * @email 136327134@qq.com + * @date 2022/9/22 + */ + public function handleNotify() + { + return $this->instance->v3pay->handleNotify(function ($notify, $successful) { + Log::error('支付回调:' . json_encode($notify)); + if ($successful && isset($notify->out_trade_no)) { + if (isset($notify->attach) && $notify->attach) { + if (($count = strpos($notify->out_trade_no, '_')) !== false) { + $notify->out_trade_no = substr($notify->out_trade_no, $count + 1); + } + return (new Hook(PayNotifyServices::class, 'wechat'))->listen($notify->attach, $notify->out_trade_no, $notify->transaction_id); + } + /** @var WechatMessageServices $wechatMessageService */ + $wechatMessageService = app()->make(WechatMessageServices::class); + $wechatMessageService->setOnceMessage($notify, $notify->openid, 'payment_success', $notify->out_trade_no); + return false; + } + }); + } +} diff --git a/crmeb/crmeb/services/pay/storage/WechatPay.php b/crmeb/crmeb/services/pay/storage/WechatPay.php index 5d22cfad1..f8ec38463 100644 --- a/crmeb/crmeb/services/pay/storage/WechatPay.php +++ b/crmeb/crmeb/services/pay/storage/WechatPay.php @@ -64,9 +64,8 @@ class WechatPay extends BasePay implements PayInterface } if (request()->isRoutine()) { // 获取配置 判断是否为新支付 - if($options['pay_new_weixin_open']) - { - return MiniProgramService::newJsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail,$options); + if ($options['pay_new_weixin_open']) { + return MiniProgramService::newJsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail, $options); } return MiniProgramService::jsPay($options['openid'], $orderId, $totalFee, $attach, $body, $detail); } @@ -114,10 +113,9 @@ class WechatPay extends BasePay implements PayInterface if (isset($opt['wechat'])) { return WechatService::refund($outTradeNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount); } else { - if($opt['pay_new_weixin_open']) - { + if ($opt['pay_new_weixin_open']) { return MiniProgramService::miniRefund($outTradeNo, $totalFee, $refundFee, $opt); - }else{ + } else { return MiniProgramService::refund($outTradeNo, $refundNo, $totalFee, $refundFee, $opUserId, $refundReason, $type, $refundAccount); } } @@ -140,7 +138,7 @@ class WechatPay extends BasePay implements PayInterface * @return mixed|\Symfony\Component\HttpFoundation\Response * @throws \EasyWeChat\Core\Exceptions\FaultException */ - public static function handleNotify() + public function handleNotify() { return WechatService::handleNotify(); } diff --git a/crmeb/public/install/crmeb.sql b/crmeb/public/install/crmeb.sql index 849eabbae..cf553d614 100644 --- a/crmeb/public/install/crmeb.sql +++ b/crmeb/public/install/crmeb.sql @@ -15057,7 +15057,7 @@ INSERT INTO `eb_lang_code` (`id`, `type_id`, `code`, `remarks`, `lang_explain`, (13530, 1, '账户充值', '账户充值', '账户充值', 0), (13531, 1, '佣金转入', '佣金转入', '佣金转入', 0), (13532, 1, '周榜', '周榜', '周榜', 0), -(13533, 1, '月榜', '月榜', '周榜', 0), +(13533, 1, '月榜', '月榜', '月榜', 0), (13534, 1, '周排行', '周排行', '周排行', 0), (13535, 1, '月排行', '月排行', '月排行', 0), (13536, 1, '语言切换', '语言切换', '语言切换', 0), @@ -17418,7 +17418,7 @@ INSERT INTO `eb_lang_code` (`id`, `type_id`, `code`, `remarks`, `lang_explain`, (15888, 3, '账户充值', '账户充值', '賬戶充值', 0), (15889, 3, '佣金转入', '佣金转入', '佣金轉入', 0), (15890, 3, '周榜', '周榜', '周榜', 0), -(15891, 3, '月榜', '月榜', '周榜', 0), +(15891, 3, '月榜', '月榜', '月榜', 0), (15892, 3, '周排行', '周排行', '週排行', 0), (15893, 3, '月排行', '月排行', '月排行', 0), (15894, 3, '语言切换', '语言切换', '語言切換', 0), @@ -25755,7 +25755,27 @@ INSERT INTO `eb_lang_code` (`id`, `type_id`, `code`, `remarks`, `lang_explain`, (24217, 10, '提醒付款通知', '提醒付款通知', 'Ghi nhớ thông báo thanh toán', 0), (24218, 10, '短信验证码', '短信验证码', 'Mã kiểm tra SMS', 0), (24219, 10, '到店自提', '到店自提', 'Tự rút lui', 0), -(24220, 10, '快递配送', '快递配送', 'Name', 0); +(24220, 10, '快递配送', '快递配送', 'Name', 0), +(24221, 1, '退款发起查询失败', '退款发起失败', '微信支付:发起退款查询失败', 0), +(24222, 2, '退款发起查询失败', '退款发起失败', 'WeChat payment: Failed to launch refund query', 0), +(24223, 3, '退款发起查询失败', '退款发起失败', '微信支付:發起退款査詢失敗', 0), +(24224, 4, '退款发起查询失败', '退款发起失败', 'Paiement Wechat: impossible dinitier la requête de remboursement', 0), +(24225, 5, '退款发起查询失败', '退款发起失败', 'Pagamento WeChat: avvio della richiesta di rimborso non riuscito', 0), +(24226, 6, '退款发起查询失败', '退款发起失败', 'WeChat Pay:返金照会の開始に失敗しました', 0), +(24227, 7, '退款发起查询失败', '退款发起失败', '위챗페이: 환불 조회 실패', 0), +(24228, 8, '退款发起查询失败', '退款发起失败', '', 0), +(24229, 9, '退款发起查询失败', '退款发起失败', 'ล้มเหลวในการเริ่มต้นการสอบถามเกี่ยวกับการคืนเงิน', 0), +(24230, 10, '退款发起查询失败', '退款发起失败', 'Dịch vụ WeChat: không thể khởi chạy yêu cầu hoàn to àn', 0), +(24231, 1, '500000', '发起退款查询失败', '微信支付:发起退款查询失败', 1), +(24232, 2, '500000', '发起退款查询失败', 'WeChat payment: Failed to launch refund query', 1), +(24233, 3, '500000', '发起退款查询失败', '微信支付:發起退款査詢失敗', 1), +(24234, 4, '500000', '发起退款查询失败', 'Paiement Wechat: impossible dinitier la requête de remboursement', 1), +(24235, 5, '500000', '发起退款查询失败', 'Pagamento WeChat: avvio della richiesta di rimborso non riuscito', 1), +(24236, 6, '500000', '发起退款查询失败', 'WeChat Pay:返金照会の開始に失敗しました', 1), +(24237, 7, '500000', '发起退款查询失败', '위챗페이: 환불 조회 실패', 1), +(24238, 8, '500000', '发起退款查询失败', '', 1), +(24239, 9, '500000', '发起退款查询失败', 'ล้มเหลวในการเริ่มต้นการสอบถามเกี่ยวกับการคืนเงิน', 1), +(24240, 10, '500000', '发起退款查询失败', 'Dịch vụ WeChat: không thể khởi chạy yêu cầu hoàn to àn', 1); -- -------------------------------------------------------- @@ -26140,24 +26160,25 @@ CREATE TABLE IF NOT EXISTS `eb_lang_type` ( `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1启用0禁用', `is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否默认语言', `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除', - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='语言类型'; -- -- 转存表中的数据 `eb_lang_type` -- -INSERT INTO `eb_lang_type` (`id`, `language_name`, `file_name`, `status`, `is_default`) VALUES -(1, '中文', 'zh-CN', 1, 1), -(2, '英文', 'en-US', 1, 0), -(3, '繁体中文', 'zh-Hant', 1, 0), -(4, '法语', 'fr-FR', 1, 0), -(5, '意大利语', 'it-IT', 1, 0), -(6, '日语', 'ja-JP', 1, 0), -(7, '韩语', 'ko-KR', 1, 0), -(8, '蒙古语', 'mn-MN', 1, 0), -(9, '泰语', 'th-TH', 1, 0), -(10, '越南语', 'vi-VN', 1, 0); +INSERT INTO `eb_lang_type` (`id`, `language_name`, `file_name`, `status`, `is_default`, `is_del`) VALUES +(1, '中文', 'zh-CN', 1, 1, 0), +(2, '英文', 'en-US', 1, 0, 0), +(3, '繁体中文', 'zh-Hant', 1, 0, 0), +(4, '法语', 'fr-FR', 1, 0, 0), +(5, '意大利语', 'it-IT', 1, 0, 0), +(6, '日语', 'ja-JP', 1, 0, 0), +(7, '韩语', 'ko-KR', 1, 0, 0), +(8, '蒙古语', 'mn-MN', 1, 0, 0), +(9, '泰语', 'th-TH', 1, 0, 0), +(10, '越南语', 'vi-VN', 1, 0, 0); -- -------------------------------------------------------- @@ -32353,7 +32374,10 @@ INSERT INTO `eb_system_config` (`id`, `menu_name`, `type`, `input_type`, `config (409, 'pay_new_weixin_open', 'radio', 'input', 4, '0=>关闭\n1=>打开', 1, '', 0, 0, '0', '小程序支付管理', '小程序开发后台有支付管理的请打开此开关', 0, 1), (410, 'pay_new_weixin_mchid', 'text', 'input', 4, '', 1, '', 0, 0, '\"\"', '小程序支付商户号', '小程序开通支付管理生成的商户号', 0, 1), (411, 'system_comment_time', 'text', 'number', 27, '', 1, '', 100, 0, '\"0\"', '自动评价时间', '自动评价时间(天),0为不开启自动评价', 0, 1), -(412, 'comment_content', 'text', 'input', 27, '', 1, '', 100, 0, '\"\\u6b64\\u7528\\u6237\\u672a\\u505a\\u8bc4\\u4ef7\"', '自动评价文字', '自动评价显示的评价文字', 0, 1); +(412, 'comment_content', 'text', 'input', 27, '', 1, '', 100, 0, '\"\\u6b64\\u7528\\u6237\\u672a\\u505a\\u8bc4\\u4ef7\"', '自动评价文字', '自动评价显示的评价文字', 0, 1), +(413, 'pay_wechat_type', 'radio', 'input', 4, '0=>v2\n1=>v3', 1, '', 0, 0, '0', '支付接口类型', '支付接口类型v2对应微信支付旧版v2支付。v3对应微信支付v3支付接口。支付证书可以通用一个。支付秘钥和v2旧版支付有区别', 10, 1), +(414, 'pay_weixin_serial_no', 'text', 'input', 4, '', 1, '', 100, 0, '\"\"', '证书序列号', '「商户API证书」的「证书序列号」,可以在证书管理里面查看', 0, 1), +(415, 'pay_weixin_key_v3', 'text', 'input', 4, '', 1, '', 100, 0, '\"\"', 'V3支付Key', 'V3支付秘钥', 0, 1); -- -------------------------------------------------------- diff --git a/crmeb/vendor/composer/installed.php b/crmeb/vendor/composer/installed.php index 801353f30..b95f20a3a 100644 --- a/crmeb/vendor/composer/installed.php +++ b/crmeb/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'topthink/think', - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => '13adf9a931c339ffb7910da803bf28c4ed4d1d9b', + 'pretty_version' => '4.6.0.x-dev', + 'version' => '4.6.0.9999999-dev', + 'reference' => '7894ca3eaf91b7c54ffb20443b7b0d51541546d3', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -764,9 +764,9 @@ 'dev_requirement' => false, ), 'topthink/think' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => '13adf9a931c339ffb7910da803bf28c4ed4d1d9b', + 'pretty_version' => '4.6.0.x-dev', + 'version' => '4.6.0.9999999-dev', + 'reference' => '7894ca3eaf91b7c54ffb20443b7b0d51541546d3', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/crmeb/vendor/overtrue/wechat/src/Foundation/Application.php b/crmeb/vendor/overtrue/wechat/src/Foundation/Application.php index 40222e9de..950bb0363 100644 --- a/crmeb/vendor/overtrue/wechat/src/Foundation/Application.php +++ b/crmeb/vendor/overtrue/wechat/src/Foundation/Application.php @@ -105,11 +105,7 @@ class Application extends Container ServiceProviders\ShakeAroundServiceProvider::class, ServiceProviders\OpenPlatformServiceProvider::class, ServiceProviders\MiniProgramServiceProvider::class, - ServiceProviders\CommentServiceProvider::class, - \crmeb\services\easywechat\subscribe\ProgramProvider::class, - \crmeb\services\easywechat\wechatlive\ProgramProvider::class, - \crmeb\services\easywechat\Open3rd\ProgramProvider::class, - \crmeb\services\easywechat\miniPayment\ServiceProvider::class + ServiceProviders\CommentServiceProvider::class ]; /** diff --git a/crmeb/vendor/services.php b/crmeb/vendor/services.php index d27548a96..2db3c373b 100644 --- a/crmeb/vendor/services.php +++ b/crmeb/vendor/services.php @@ -1,5 +1,5 @@ 'think\\captcha\\CaptchaService',