diff --git a/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php b/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php index e3ab8bae..0cb3f12c 100644 --- a/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php +++ b/niucloud/app/adminapi/controller/customer_resources/CustomerResources.php @@ -67,9 +67,9 @@ class CustomerResources extends BaseAdminController ["optional_class_time",""], ["distance",""], ["decision_maker",""], - ["initial_intent",""], + ["initial_intent",null], ["campus",""], - ["status",""], + ["status",null], ['member_label', []], ["create_year_month",date("Y-m")], @@ -110,9 +110,9 @@ class CustomerResources extends BaseAdminController ["optional_class_time",""], ["distance",""], ["decision_maker",""], - ["initial_intent",""], + ["initial_intent",null], ["campus",""], - ["status",""], + ["status",null], ['member_label', []], ["create_year_month",date("Y-m")], ["create_date",date("Y-m-d")], diff --git a/niucloud/app/adminapi/controller/order_table/OrderTable.php b/niucloud/app/adminapi/controller/order_table/OrderTable.php index 195b0d8c..5b0843f5 100644 --- a/niucloud/app/adminapi/controller/order_table/OrderTable.php +++ b/niucloud/app/adminapi/controller/order_table/OrderTable.php @@ -29,7 +29,8 @@ class OrderTable extends BaseAdminController public function lists(){ $data = $this->request->params([ ["order_status",""], - ["payment_type",""] + ["payment_type",""], + ["resource_id",""] ]); return success((new OrderTableService())->getPage($data)); } diff --git a/niucloud/app/adminapi/controller/pay/Pay.php b/niucloud/app/adminapi/controller/pay/Pay.php index dcfc750f..d9d69f55 100644 --- a/niucloud/app/adminapi/controller/pay/Pay.php +++ b/niucloud/app/adminapi/controller/pay/Pay.php @@ -109,4 +109,22 @@ class Pay extends BaseAdminController { return success(data:(new PayService())->getPayTypeList()); } + + + public function order_pay(){ + $data = $this->request->params([ + ['order_id', ''], + ]); + + return success(data:(new PayService())->order_pay($data)); + } + + public function check_payment_status(){ + $data = $this->request->params([ + ['out_trade_no', ''], + ]); + + return success(data:(new PayService())->check_payment_status($data)); + } + } diff --git a/niucloud/app/adminapi/route/pay.php b/niucloud/app/adminapi/route/pay.php index f5b996d6..9d3ed364 100644 --- a/niucloud/app/adminapi/route/pay.php +++ b/niucloud/app/adminapi/route/pay.php @@ -68,6 +68,11 @@ Route::group('pay', function () { Route::get('type/list', 'pay.Pay/payTypeList'); //找朋友帮忙付支付信息 Route::get('friendspay/info/:trade_type/:trade_id/:channel', 'pay.Pay/friendspayInfo'); + + Route::post('order_pay', 'pay.Pay/order_pay'); + + Route::post('check_payment_status', 'pay.Pay/check_payment_status'); + })->middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/api/controller/login/Login.php b/niucloud/app/api/controller/login/Login.php index 4a5b2b83..6bce779e 100644 --- a/niucloud/app/api/controller/login/Login.php +++ b/niucloud/app/api/controller/login/Login.php @@ -12,11 +12,16 @@ namespace app\api\controller\login; use app\dict\member\MemberLoginTypeDict; +use app\model\sys\SysConfig; +use app\service\admin\sys\SystemService; use app\service\api\captcha\CaptchaService; use app\service\api\login\ConfigService; use app\service\api\login\LoginService; use core\base\BaseController; +use core\pay\PayLoader; +use core\pay\Wechatpay; use Exception; +use think\facade\Db; use think\Response; class Login extends BaseController @@ -131,4 +136,45 @@ class Login extends BaseController return success($result);//code|1正确 } + + public function test(){ + $pay_config = Db::name("campus_pay")->where(['campus_id' => 1])->find(); + + $sysConfig = new SysConfig(); + + $vx_config = $sysConfig->where(['config_key' => 'WECHAT'])->value("value"); + + $config = [ + // 必填-商户号 + 'mch_id' => $pay_config['mchid'], + // 必填-商户私钥 字符串或路径 + 'mch_secret_cert' => $pay_config['apiclient_cert'], + // 必填-商户公钥证书路径 + 'mch_public_cert_path' => $pay_config['apiclient_key'], + // 必填 + 'notify_url' => 'https://zh.hnhbty.cn/api/pay/qrcodenotify', + // 选填-公众号 的 app_id + 'mp_app_id' => $vx_config['app_id'], + // 选填-小程序 的 app_id + 'mini_app_id' => '', + 'mch_secret_key' => $pay_config['pay_sign_key'], + ]; + $params = [ + 'out_trade_no' => '123123', + 'body' => '测试', + 'money' => 100, + ]; + $pay = new PayLoader('Wechatpay', $config); + + $url = $pay->scan($params); + + $path = qrcode( + $url['code_url'], + '', + [], + 'upload/qrcode/pay/' + ); + + echo "";die; + } } diff --git a/niucloud/app/api/controller/pay/Pay.php b/niucloud/app/api/controller/pay/Pay.php index 4b68528f..f4757902 100644 --- a/niucloud/app/api/controller/pay/Pay.php +++ b/niucloud/app/api/controller/pay/Pay.php @@ -108,11 +108,14 @@ class Pay extends BaseApiController return success('SUCCESS',(new PayService())->getQrcode($data['type'], $data['trade_type'], $data['trade_id'])); } - public function qrcodeNotify() + public function qrcodeNotify(int $order_id) { // todo - Log::debug('qrcodeNotify'); - Log::debug(json_encode($this->request->param())); + + $data = $this->request->param(); + + (new PayService())->qrcodeNotify($data,$order_id); + return success('SUCCESS'); } } diff --git a/niucloud/app/api/route/pay.php b/niucloud/app/api/route/pay.php index 4d41f42d..f420ab85 100644 --- a/niucloud/app/api/route/pay.php +++ b/niucloud/app/api/route/pay.php @@ -20,7 +20,7 @@ Route::any('pay/notify/:channel/:type/:action', 'pay.Pay/notify') ->middleware(ApiCheckToken::class) ->middleware(ApiLog::class); -Route::any('pay/qrcodenotify', 'pay.Pay/qrcodeNotify') +Route::any('pay/qrcodenotify/order_id/:order_id', 'pay.Pay/qrcodeNotify') ->middleware(ApiChannel::class) ->middleware(ApiCheckToken::class) ->middleware(ApiLog::class); diff --git a/niucloud/app/api/route/route.php b/niucloud/app/api/route/route.php index c88b5ab9..8c10a1c0 100644 --- a/niucloud/app/api/route/route.php +++ b/niucloud/app/api/route/route.php @@ -151,6 +151,9 @@ Route::group(function () { Route::get('task/growth', 'sys.Task/growth'); // 获取积分任务 Route::get('task/point', 'sys.Task/point'); + + + Route::get('test', 'login.Login/test'); })->middleware(ApiChannel::class) ->middleware(ApiCheckToken::class) ->middleware(ApiLog::class); diff --git a/niucloud/app/common.php b/niucloud/app/common.php index 4c99d0f2..3948d0ef 100644 --- a/niucloud/app/common.php +++ b/niucloud/app/common.php @@ -2,6 +2,7 @@ use app\model\campus_person_role\CampusPersonRole; use app\model\personnel\Personnel; +use app\model\sys\SysConfig; use think\Container; use think\Response; use think\facade\Lang; @@ -1084,4 +1085,58 @@ function getEmployeeNumber() $max_id = $personnel->max('id') + 1; $max_id = str_pad($max_id, 5, '0', STR_PAD_LEFT); return date('Ymd') . $max_id; -} \ No newline at end of file +} + +function return_pay_config($campus_id,$order_id){ + $campus_pay = new \app\model\campus_pay\CampusPay(); + $pay_config = $campus_pay->where(['campus_id' => $campus_id])->find(); + + $sysConfig = new SysConfig(); + + $vx_config = $sysConfig->where(['config_key' => 'WECHAT'])->value("value"); + + $config = [ + // 必填-商户号 + 'mch_id' => $pay_config['mchid'], + // 必填-商户私钥 字符串或路径 + 'mch_secret_cert' => $pay_config['apiclient_cert'], + // 必填-商户公钥证书路径 + 'mch_public_cert_path' => $pay_config['apiclient_key'], + // 必填 + 'notify_url' => 'https://zh.hnhbty.cn/api/pay/qrcodenotify/order_id/'.$order_id, + // 选填-公众号 的 app_id + 'mp_app_id' => $vx_config['app_id'], + // 选填-小程序 的 app_id + 'mini_app_id' => '', + 'mch_secret_key' => $pay_config['pay_sign_key'], + ]; + + return $config; +} + +function getCurrentDomain() +{ + $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || + $_SERVER['SERVER_PORT'] == 443 ? "https://" : "http://"; + + $host = $_SERVER['HTTP_HOST']; // 包括域名和端口(如存在) + + return $scheme . $host.'/'; +} + +function decryptWechatPayNotify($ciphertext, $nonce, $associatedData, $key) +{ + $ciphertext = base64_decode($ciphertext); + $authTag = substr($ciphertext, -16); + $ciphertext = substr($ciphertext, 0, -16); + + return openssl_decrypt( + $ciphertext, + 'aes-256-gcm', + $key, + OPENSSL_RAW_DATA, + $nonce, + $authTag, + $associatedData + ); +} diff --git a/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php b/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php index a752cf5d..ede26799 100644 --- a/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php +++ b/niucloud/app/service/admin/customer_resources/CustomerResourcesService.php @@ -134,6 +134,7 @@ class CustomerResourcesService extends BaseAdminService if(!$data['consultant']){ return fail("操作失败"); } + $sixSpeed = new SixSpeed(); // $data['member_label'] = json_encode($data['member_label']); @@ -150,6 +151,7 @@ class CustomerResourcesService extends BaseAdminService ]); if($data['purchase_power']){ + $six_id = $sixSpeed->where(['resource_id' => $res->id])->value("id"); $data['staff_id'] = $data['consultant']; @@ -235,7 +237,7 @@ class CustomerResourcesService extends BaseAdminService if($data['purchase_power']){ $sixSpeedModificationLog = new SixSpeedModificationLog(); $six_id = $sixSpeed->where(['resource_id' => $id])->value("id"); -// $data['staff_id'] = $data['consultant']; + $data['staff_id'] = $res['consultant']; @@ -251,7 +253,7 @@ class CustomerResourcesService extends BaseAdminService 'first_visit_status' => $data['first_visit_status'], 'second_visit_status' => $data['second_visit_status'], 'is_closed' => $data['is_closed'], -// 'staff_id' => $data['staff_id'], + 'staff_id' => $data['staff_id'], 'resource_id' => $id ]; if($six_id){ diff --git a/niucloud/app/service/admin/order_table/OrderTableService.php b/niucloud/app/service/admin/order_table/OrderTableService.php index cfd54c7b..b5d245c9 100644 --- a/niucloud/app/service/admin/order_table/OrderTableService.php +++ b/niucloud/app/service/admin/order_table/OrderTableService.php @@ -43,7 +43,7 @@ class OrderTableService extends BaseAdminService $field = 'id,resource_id,payment_id,order_status,payment_type,order_amount,course_id,class_id,staff_id,after_sales_status,after_sales_reason,after_sales_time,created_at,updated_at,payment_time,subscription_payment_time'; $order = 'id desc'; - $search_model = $this->model->withSearch(["order_status","payment_type"], $where)->with(['customerResources','course','classGrade','personnel'])->field($field)->order($order); + $search_model = $this->model->withSearch(["order_status","payment_type","resource_id"], $where)->with(['customerResources','course','classGrade','personnel'])->field($field)->order($order); $list = $this->pageQuery($search_model); return $list; } diff --git a/niucloud/app/service/admin/pay/PayService.php b/niucloud/app/service/admin/pay/PayService.php index a0a8f353..8efea3d3 100644 --- a/niucloud/app/service/admin/pay/PayService.php +++ b/niucloud/app/service/admin/pay/PayService.php @@ -14,13 +14,16 @@ namespace app\service\admin\pay; use app\dict\common\ChannelDict; use app\dict\pay\PayDict; use app\dict\pay\PaySceneDict; +use app\model\customer_resources\CustomerResources; use app\model\member\Member; +use app\model\order_table\OrderTable; use app\model\pay\Pay; use app\model\sys\Poster; use app\service\core\pay\CorePayService; use app\service\core\paytype\CoreOfflineService; use app\service\core\sys\CoreSysConfigService; use core\base\BaseAdminService; +use core\pay\PayLoader; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; @@ -220,4 +223,33 @@ class PayService extends BaseAdminService } return $pay_type_list; } + + public function order_pay($data){ + $out_trade_no = 'sm'.date("YmdHis").time(); + $order = new OrderTable(); + $order_info = $order->where(['id' => $data['order_id']])->find(); + $cr = new CustomerResources(); + $resource_info = $cr->where(['id' => $order_info['resource_id']])->find(); + $config = return_pay_config($resource_info['campus'],$data['order_id']); + + $params = [ + 'out_trade_no' => $out_trade_no, + 'body' => '订单扫码支付:'.$out_trade_no, + 'money' => $order_info['order_amount'] * 100, + ]; + + $pay = new PayLoader('Wechatpay', $config); + + $url = $pay->scan($params); + $path = qrcode($url['code_url'],'',[],'upload/qrcode/pay/'); + + $order->where(['id' => $data['order_id']])->update(['payment_id' => $out_trade_no,'ipv3' => $config['mch_secret_key']]); + return ['qrcode_url' => getCurrentDomain().$path,'out_trade_no'=>$out_trade_no]; + } + + public function check_payment_status($data){ + $order = new OrderTable(); + $order_status = $order->where(['payment_id' => $data['out_trade_no']])->value("order_status"); + return ['order_status'=>$order_status]; + } } diff --git a/niucloud/app/service/api/pay/PayService.php b/niucloud/app/service/api/pay/PayService.php index 6fced6a9..37dc895f 100644 --- a/niucloud/app/service/api/pay/PayService.php +++ b/niucloud/app/service/api/pay/PayService.php @@ -15,6 +15,7 @@ use app\dict\common\ChannelDict; use app\dict\pay\PayDict; use app\dict\pay\PaySceneDict; use app\model\member\Member; +use app\model\order_table\OrderTable; use app\model\pay\Pay; use app\model\sys\Poster; use app\service\core\member\CoreMemberService; @@ -24,6 +25,7 @@ use core\exception\ApiException; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; +use think\facade\Log; /** * 支付业务 @@ -158,8 +160,23 @@ class PayService extends BaseApiService /** * 二维码支付回调 */ - public function qrcodeNotify() + public function qrcodeNotify($data,$order_id) { - // todo + + $order = new OrderTable(); + $order_info = $order->where(['id' => $order_id])->find(); + if($order_info['order_status'] == 'pending' and !empty($order_info['ipv3'])){ + $resource = $data['resource']; + $decrypted = decryptWechatPayNotify( + $resource['ciphertext'], + $resource['nonce'], + $resource['associated_data'], + $order_info['ipv3'] + ); + $info = json_decode($decrypted, true); + + $order->where(['payment_id' => $info['out_trade_no']])->update(['order_status' => 'paid','payment_time' => date("Y-m-d H:i:s")]); + } + } } diff --git a/niucloud/app/validate/customer_resources/CustomerResources.php b/niucloud/app/validate/customer_resources/CustomerResources.php index e31a70b4..76031ed3 100644 --- a/niucloud/app/validate/customer_resources/CustomerResources.php +++ b/niucloud/app/validate/customer_resources/CustomerResources.php @@ -56,8 +56,8 @@ class CustomerResources extends BaseValidate ]; protected $scene = [ - "add" => ['source', 'source_channel', 'name', 'age', 'gender', 'phone_number', 'demand', 'purchasing_power', 'cognitive_idea', 'optional_class_time', 'distance', 'decision_maker', 'initial_intent', 'campus', 'status'], - "edit" => ['source', 'source_channel', 'name', 'age', 'gender', 'phone_number', 'demand', 'purchasing_power', 'cognitive_idea', 'optional_class_time', 'distance', 'decision_maker', 'initial_intent', 'campus', 'status'] + "add" => ['source', 'source_channel', 'name', 'age', 'gender', 'phone_number', 'demand', 'purchasing_power', 'cognitive_idea'], + "edit" => ['source', 'source_channel', 'name', 'age', 'gender', 'phone_number', 'demand', 'purchasing_power', 'cognitive_idea'] ]; } diff --git a/niucloud/composer.json b/niucloud/composer.json index 18a3b98b..36505d92 100644 --- a/niucloud/composer.json +++ b/niucloud/composer.json @@ -58,7 +58,8 @@ "workerman/redis-queue": "v1.2.0", "workerman/crontab": "v1.0.6", "hyperf/pimple": "~2.2.0", - "365taofang/huaweicloud-sdk-php-obs": "^3.23" + "365taofang/huaweicloud-sdk-php-obs": "^3.23", + "ext-openssl": "*" }, "require-dev": { "symfony/var-dumper": "v6.0.19", @@ -90,4 +91,4 @@ "url": "https://mirrors.aliyun.com/composer" } } -} \ No newline at end of file +} diff --git a/niucloud/core/pay/Wechatpay.php b/niucloud/core/pay/Wechatpay.php index 28568a58..8aae6d52 100644 --- a/niucloud/core/pay/Wechatpay.php +++ b/niucloud/core/pay/Wechatpay.php @@ -211,9 +211,9 @@ class Wechatpay extends BasePay ], ])); } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } +// if ($e instanceof InvalidResponseException) { +// throw new PayException($e->response->all()['message'] ?? ''); +// } throw new PayException($e->getMessage()); } }