diff --git a/.env b/.env
index f0a1a12..d6326f0 100755
--- a/.env
+++ b/.env
@@ -1 +1 @@
-APP_DEBUG = false
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 124.71.161.49
DATABASE = cxhxy
USERNAME = cxhxy
PASSWORD = FmfbjEeHfYKZHHK7
HOSTPORT = 3306
CHARSET = utf8
DEBUG = false
\ No newline at end of file
+APP_DEBUG = false
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 124.71.161.49
DATABASE = cxhxy
USERNAME = cxhxy
PASSWORD = FmfbjEeHfYKZHHK7
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
\ No newline at end of file
diff --git a/extend/hema/wechat/Pay.php b/extend/hema/wechat/Pay.php
index 5b377b0..b18fcde 100755
--- a/extend/hema/wechat/Pay.php
+++ b/extend/hema/wechat/Pay.php
@@ -1,1164 +1,1181 @@
-isp_config = Setting::getItem('wxpayisp',0);
- $this->config = $config;
- }
-
- /********** V3接口 **********/
-
- /**
- * H5下单API
- * $out_trade_no=订单号, $total=支付金额,,$attach=订单描述
- * $profit_sharing=是否分账(有配送费要分账时传递)
- */
- public function h5($out_trade_no,$total,$notify_url,$attach='订单支付',$profit_sharing = false)
- {
- $params = [
- 'description' => $attach,//商品描述
- 'out_trade_no' => $out_trade_no,//商户订单号
- 'attach' => $attach,//附加数据
- 'notify_url' => base_url() . $notify_url, //通知地址
- 'amount' => [
- 'total' => intval($total * 100),//订单总金额,单位为分
- ],
- 'scene_info' => [
- 'payer_client_ip' => \request()->ip(),//用户终端IP
- ],
- 'h5_info' => [
- 'type' => 'Wap'
- ]
- ];
- if($this->config['is_sub'] == 1){
- //服务商
- $params['sp_appid'] = $this->isp_config['app_id'];//服务商应用ID
- $params['sp_mchid'] = $this->isp_config['mch_id'];//服务商商户号
- $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
- $params['sub_mchid'] = $this->config['mch_id'];//子商户号
- $url = $this->getUrl('pay/partner/transactions/h5');//服务商
- $is_isp = true;
- }else{
- //直连商户
- $params['appid'] = $this->config['app_id'];//小程序ID
- $params['mchid'] = $this->config['mch_id'];//商户号
- $url = $this->getUrl('pay/transactions/h5');//直连商户
- $is_isp = false;
- }
- //判断是否开启分账
- $divide = Setting::getItem('divide',0);
- if($profit_sharing or $divide['extract'] > 0){
- $params['settle_info']['profit_sharing'] = true; //开启分账
- }
- $params = hema_json($params);
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
- ];
- $result = json_decode(Http::post($url, $params,[],$headers),true);
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- return $result['h5_url'];
- }
- //扣取手续费 按照0.6%计算
- private function serviceFee($fee)
- {
- return intval(($fee - ($fee * 6 / 1000)) * 100);
- }
- /**
- * 分账
- * $data:数组 =分账数据
- * [
- * out_order_no:第三方订单号
- * transaction_id:微信订单号
- * total:分账总金额
- * ]
- * $applet_id=小程序编号
- * $delivery_fee=配送费分账金额
- */
- public function divide($data,$applet_id='',$delivery_fee=0)
- {
- $is_divide = false;//是否分账
- $total = $data['total'];//分账总金额
- $service_fee = 0;//平台分账金额(单位分)
- $agent_fee = 0;//代理分账金额(单位分)
- $agent_openid = '';//代理收款账号
- //判断外卖订单是否分账配送费
- if($delivery_fee > 0){
- $total = $total - $delivery_fee;
- $delivery_fee = $this->serviceFee($delivery_fee);//去掉手续费
- $is_divide = true; //配送费大于0 开启分账
- }
- $divide = Setting::getItem('divide',0); //分佣参数
- $applet = Applet::get($applet_id);//获取商家应用
- //如果开启分佣
- if($divide['extract'] > 0){
- $extract = $total * $divide['extract'] / 100;//抽取金额
- $service_fee = $this->serviceFee($extract);//去掉手续费
- if($divide['agent_extract'] > 0){
- //判断商家是否有代理商
- if($applet['agent_id'] > 0){
- if($account = DivideAccount::withoutGlobalScope()->where('applet_id',$applet_id)->find()){
- if(!empty($account['open_id'])){
- $agent_openid = $account['open_id'];
- $agent_fee = $this->serviceFee($extract * $divide['agent_extract'] / 100);//去掉手续费
- $service_fee = $service_fee - $agent_fee;
- }
- }
- }
- }
- $is_divide = true; //开启分账
- }
- //判断是否要进行分账
- if(!$is_divide){
- $this->error = '不用分账';
- return false;
- }
- //***************** 添加分账接收方 *********************//
- $receivers = [];//收款方账号列表
- //添加平台收佣账号
- if(($service_fee + $delivery_fee) > 0){
- if(!$this->addReceivers($applet_id)) {
- $this->error = '添加平台分账接收方失败';
- return false;
- }
- $webpay = Setting::getItem('webpay',0)['wx']; //平台微信支付参数
- $receivers[] = [
- 'type' => 'MERCHANT_ID',//分账接收方类型 MERCHANT_ID=商户号 PERSONAL_OPENID=个人openid
- 'account' => $webpay['mch_id'],//分账接收方账号
- 'amount' => $service_fee + $delivery_fee,//分账金额
- 'description' => '分佣给平台',//分账描述
- ];
- }
- //添加代理收佣账号
- if($agent_fee > 0 and !empty($agent_openid)){
- if(!$this->addReceivers($applet_id,false,$agent_openid)) {
- $this->error = '添加代理分账接收方失败';
- return false;
- }
- $receivers[] = [
- 'type' => $this->config['is_sub'] == 1 ? 'PERSONAL_SUB_OPENID':'PERSONAL_OPENID',//分账接收方类型
- 'account' => $agent_openid,//分账接收方账号
- 'amount' => $agent_fee,//分账金额
- 'description' => '分佣给代理',//分账描述
- ];
- }
- //***************** 请求分账 *********************//
- if(sizeof($receivers) == 0){
- $this->error = '收款方账号列表为空';
- return false;
- }
- if(!$this->profitSharing($data['transaction_id'],$data['out_order_no'],$receivers)) {
- $this->error = '请求分账失败';
- return false;
- }
- //***************** 添加交易记录 *********************//
- $record_log = [];//交易流水记录
- //是否增加平台分红记录(分佣)
- if(($service_fee - $agent_fee) > 0){
- $money = sprintf("%.2f",$service_fee / 100);//计算金额
- //平台分红(分佣)记录
- array_push($record_log,[
- 'mode' => 40, //赠送
- 'type' => 30, //微信
- 'order_no' => $data['out_order_no'],
- 'money' => $money,
- 'remark' => '交易分佣'
- ]);
- //商户扣费记录
- array_push($record_log,[
- 'mode' => 50, //扣减
- 'type' => 30, //微信
- 'order_no' => $data['out_order_no'],
- 'money' => $money,
- 'user_id' => $applet['user_id'],
- 'remark' => '交易服务费'
- ]);
- }
- //是否增加配送费记录
- if($delivery_fee > 0){
- $money = sprintf("%.2f",$delivery_fee / 100);//计算金额
- //平台收取记录
- array_push($record_log,[
- 'mode' => 40, //赠送
- 'type' => 30, //微信
- 'order_no' => $data['out_order_no'],
- 'money' => $money,
- 'remark' => '第三方配送费'
- ]);
- //商户扣费记录
- array_push($record_log,[
- 'mode' => 50, //扣减
- 'type' => 30, //微信
- 'order_no' => $data['out_order_no'],
- 'money' => $money,
- 'user_id' => $applet['user_id'],
- 'remark' => '第三方配送费'
- ]);
- }
- //是否增加代理分佣记录
- if($agent_fee > 0){
- $money = sprintf("%.2f",$agent_fee / 100);//计算金额
- //平台收取记录
- array_push($record_log,[
- 'mode' => 40, //赠送
- 'type' => 30, //微信
- 'order_no' => $data['out_order_no'],
- 'money' => $money,
- 'user_id' => $applet['agent_id'],
- 'remark' => '交易分佣'
- ]);
- }
- //批量增加交易记录
- $model = new Record;
- if(!$model->saveAll($record_log)){
- $this->error = '添加交易记录失败';
- return false;
- }
- return true;
- }
- /**
- * 请求分账API
- */
- private function profitSharing($transaction_id,$out_order_no,$receivers)
- {
- //服务商
- $params = [
- 'transaction_id' => $transaction_id,//微信订单号
- 'out_order_no' => $out_order_no,//商户分账单号
- 'receivers' => $receivers,
- 'unfreeze_unsplit' => true,//是否解冻剩余未分资金
- ];
- if($this->config['is_sub'] == 1){
- //服务商
- $params['appid'] = $this->isp_config['app_id'];//服务商应用ID
- $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
- $params['sub_mchid'] = $this->config['mch_id'];//子商户号
- $is_isp = true;
- }else{
- //直连商户
- $params['appid'] = $this->config['app_id'];//小程序ID
- $is_isp = false;
- }
- $params = hema_json($params);
- $url = $this->getUrl('profitsharing/orders');
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
- 'Wechatpay-Serial:' . $this->isp_config['serial_no'],
- ];
- return $this->result(json_decode(Http::post($url, $params,[],$headers),true));
- }
- /**
- * 添加分账接收方API
- * $is_mchid = 接收方是否是商户 $account = 接收账号
- */
- private function addReceivers($applet_id,$is_mchid=true,$account='')
- {
- if($this->config['is_sub'] == 1){
- //服务商
- $params['appid'] = $this->isp_config['app_id'];//服务商应用ID
- $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
- $params['sub_mchid'] = $this->config['mch_id'];//子商户号
- if($is_mchid){
- $webpay = Setting::getItem('webpay',0)['wx'];
- $params['type'] = 'MERCHANT_ID';//分账接收方类型
- $params['account'] = $webpay['mch_id'];//分账接收方账号
- $params['name'] = $this->getEncrypt($webpay['name']); //(加密)分账个人接收方姓名 分账接收方类型是MERCHANT_ID时,是商户全称(必传)
- }else{
- $params['type'] = 'PERSONAL_SUB_OPENID';//分账接收方类型
- $params['account'] = $account;//分账接收方账号
- }
- $params['relation_type'] = 'SERVICE_PROVIDER'; //与分账方的关系类型 服务商
- $is_isp = true;
- $serial_no = $this->isp_config['serial_no'];
- }else{
- //直连商户
- $params['appid'] = $this->config['app_id'];//小程序ID
- if($is_mchid){
- $webpay = Setting::getItem('webpay',0)['wx'];
- $params['type'] = 'MERCHANT_ID';//分账接收方类型
- $params['account'] = $webpay['mch_id'];//分账接收方账号
- $params['name'] = $this->getEncrypt($webpay['name'],false,$applet_id); //(加密)分账个人接收方姓名 分账接收方类型是MERCHANT_ID时,是商户全称(必传)
- }else{
- $params['type'] = 'PERSONAL_OPENID';//分账接收方类型
- $params['account'] = $account;//分账接收方账号
- }
- $params['relation_type'] = 'PARTNER'; ////与分账方的关系类型 合作伙伴
- $is_isp = false;
- $serial_no = $this->config['serial_no'];
- }
- $params = hema_json($params);
- $url = $this->getUrl('profitsharing/receivers/add');
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
- 'Wechatpay-Serial:' . $serial_no,
- ];
- return $this->result(json_decode(Http::post($url, $params,[],$headers),true));
- }
- /**
- * 申请退款API
- */
- public function refunds($transaction_id,$out_refund_no,$refund_fee,$total_fee,$notify_url='',$reason='')
- {
- $params = [
- 'transaction_id' => $transaction_id,//微信支付订单号
- 'out_refund_no' => $out_refund_no,//退款订单号
- 'amount' => [
- 'refund' => intval($refund_fee * 100), // 退款金额,价格:单位分
- 'total' => intval($total_fee * 100), // 订单金额,价格:单位分
- 'currency' => 'CNY', //退款币种 只支持人民币:CNY
- ],
- ];
- if($this->config['is_sub'] == 1){
- //服务商
- $params['sub_mchid'] = $this->config['mch_id'];//子商户号
- $is_isp = true;
- }else{
- $is_isp = false;
- }
- !empty($reason) && $params['reason'] = $reason;//退款原因
- !empty($notify_url) && $params['notify_url'] = base_url() . $notify_url; // 异步通知地址
-
- $params = hema_json($params);
- $url = $this->getUrl('refund/domestic/refunds');
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
- ];
- return $this->result(json_decode(Http::post($url, $params,[],$headers),true));
-
- }
- /**
- * 退款成功异步通知
- */
- public function refundsNotify($Model,$applet_id='')
- {
- //接收微信服务器回调的数据流
- if (!$json = file_get_contents('php://input')) {
- $this->returnHttpCode(false);
- }
- // 将服务器返回的json数据转化为数组
- $result = json_decode($json,true);
- if(empty($applet_id)){
- $this->config = Setting::getItem('webpay',0)['wx'];//平台商户支付参数
- }else{
- $this->config = Setting::getItem('wxpay',$applet_id);//商家商户支付参数
- }
- if($this->config['is_sub'] == 1){
- //服务商
- $api_key = $this->isp_config['api_key'];
- //判断平台证书是否过期
- if($this->isp_config['expire_time'] < time()){
- //更新平台证书
- if(!$this->certificates()){
- $this->returnHttpCode(false,$this->error);//更新失败
- }
- }
- }else{
- //直连商户
- $api_key = $this->config['api_key'];
- //判断平台证书是否过期
- if($this->config['expire_time'] < time()){
- //更新平台证书
- if(!$this->certificates(false,$applet_id)){
- $this->returnHttpCode(false,$this->error);//更新失败
- }
- }
- }
- if(!$decrypt = new AesUtil($api_key)){
- $this->returnHttpCode(false,$decrypt->getError());
- }
- if(!$res = $decrypt->decryptToString($result['resource']['associated_data'], $result['resource']['nonce'], $result['resource']['ciphertext'])){
- $this->returnHttpCode(false,$decrypt->getError());
- }
- $data = json_decode($res,true);
- // 订单信息
- if(!$order = $Model->refundDetail($data['out_refund_no'])){
- $this->returnHttpCode(false,'订单不存在');
- }
-
- if($data['refund_status'] == 'SUCCESS') {
- // 更新订单状态
- $order->updateRefundStatus($data['refund_id']);
- $this->returnHttpCode(true);// 返回状态
- }
- $this->returnHttpCode(false, '退款失败');
- }
- /**
- * Native下单API
- * $out_trade_no=订单号, $total=支付金额,$attach=订单描述 $profit_sharing=是否分账
- */
- public function native($out_trade_no,$total,$notify_url,$attach='订单支付',$profit_sharing = false)
- {
- $params = [
- 'description' => $attach,//商品描述
- 'out_trade_no' => $out_trade_no,//商户订单号
- 'attach' => $attach,//附加数据
- 'notify_url' => base_url() . $notify_url, //通知地址
- 'amount' => [
- 'total' => intval($total * 100),//订单总金额,单位为分
- ],
- 'scene_info' => [
- 'payer_client_ip' => \request()->ip(),//用户终端IP
- ],
- ];
- if($this->config['is_sub'] == 1){
- //服务商
- $params['sp_appid'] = $this->isp_config['app_id'];//服务商应用ID
- $params['sp_mchid'] = $this->isp_config['mch_id'];//服务商商户号
- //$params['sub_appid'] = $this->config['app_id'];//子商户应用ID
- $params['sub_mchid'] = $this->config['mch_id'];//子商户号
- //$params['payer']['sub_openid'] = $openid; //子用户标识Openid
- $url = $this->getUrl('pay/partner/transactions/native');//服务商
- $is_isp = true;
- }else{
- //直连商户
- $params['appid'] = $this->config['app_id'];//小程序ID
- $params['mchid'] = $this->config['mch_id'];//商户号
- $url = $this->getUrl('pay/transactions/native');//直连商户
- $is_isp = false;
- }
- //判断是否开启分账
- $divide = Setting::getItem('divide',0);
- if($profit_sharing or $divide['extract'] > 0){
- $params['settle_info']['profit_sharing'] = true; //开启分账
- }
- $params = hema_json($params);
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
- ];
- $result = json_decode(Http::post($url, $params,[],$headers),true);
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- if(!isset($result['code_url'])){
- $this->error = 'Native下单接口请求失败';
- return false;
- }
- return $result['code_url'];
- }
- /**
- * JSAPI下单API
- * $out_trade_no=订单号, $total=支付金额,$openid=微信用户ID, ,$attach=订单描述
- * $profit_sharing=是否分账(有配送费要分账时传递)
- */
- public function jsapi($out_trade_no,$total,$openid,$notify_url,$attach='订单支付',$profit_sharing = false)
- {
- $params = [
- 'description' => $attach,//商品描述
- 'attach' => $attach,//附加数据
- 'out_trade_no' => $out_trade_no,//商户订单号
- 'notify_url' => base_url() . $notify_url, //通知地址
- 'amount' => [
- 'total' => intval($total * 100),//订单总金额,单位为分
- ],
- 'scene_info' => [
- 'payer_client_ip' => \request()->ip(),//用户终端IP
- ],
- ];
- if($this->config['is_sub'] == 1){
- //服务商
- $params['sp_appid'] = $this->isp_config['app_id'];//服务商应用ID
- $params['sp_mchid'] = $this->isp_config['mch_id'];//服务商商户号
- $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
- $params['sub_mchid'] = $this->config['mch_id'];//子商户号
- $params['payer']['sub_openid'] = $openid; //子用户标识Openid
- $url = $this->getUrl('pay/partner/transactions/jsapi');//服务商
- $is_isp = true;
- }else{
- //直连商户
- $params['appid'] = $this->config['app_id'];//小程序ID
- $params['mchid'] = $this->config['mch_id'];//商户号
- $params['payer']['openid'] = $openid; //用户标识Openid
- $url = $this->getUrl('pay/transactions/jsapi');//直连商户
- $is_isp = false;
- }
- //判断是否开启分账
- $divide = Setting::getItem('divide',0);
- if($profit_sharing or $divide['extract'] > 0){
- $params['settle_info']['profit_sharing'] = true; //开启分账
- }
- $params = hema_json($params);
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
- ];
- $result = json_decode(Http::post($url, $params,[],$headers),true);
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- if(!isset($result['prepay_id'])){
- $this->error = 'JSAPI下单接口请求失败';
- return false;
- }
- $data = [
- 'timeStamp' => (string)time(),
- 'nonceStr' => $this->nonce(),
- 'package' => 'prepay_id=' . $result['prepay_id'],
- 'signType' => 'RSA',
- ];
- $data['paySign'] = $this->paySign($data);
- return $data;
- }
-
- /**
- * 支付成功异步通知
- */
- public function notify($Model,$applet_id,$method='edit')
- {
- //接收微信服务器回调的数据流
- if (!$json = file_get_contents('php://input')) {
- $this->returnHttpCode(false);
- }
- // 将服务器返回的json数据转化为数组
- $result = json_decode($json,true);
- if(empty($applet_id)){
- $this->config = Setting::getItem('webpay',0)['wx'];//平台商户支付参数
- }else{
- $this->config = Setting::getItem('wxpay',$applet_id);//商家商户支付参数
- }
- if($this->config['is_sub'] == 1){
- //服务商
- $api_key = $this->isp_config['api_key'];
- //判断平台证书是否过期
- if($this->isp_config['expire_time'] < time()){
- //更新平台证书
- if(!$this->certificates()){
- $this->returnHttpCode(false,$this->error);//更新失败
- }
- }
- }else{
- //直连商户
- $api_key = $this->config['api_key'];
- //判断平台证书是否过期
- if($this->config['expire_time'] < time()){
- //更新平台证书
- if(!$this->certificates(false,$applet_id)){
- $this->returnHttpCode(false,$this->error);//更新失败
- }
- }
- }
- if(!$decrypt = new AesUtil($api_key)){
- $this->returnHttpCode(false,$decrypt->getError());
- }
- if(!$res = $decrypt->decryptToString($result['resource']['associated_data'], $result['resource']['nonce'], $result['resource']['ciphertext'])){
- $this->returnHttpCode(false,$decrypt->getError());
- }
- $data = json_decode($res,true);
- // 订单信息
- if(!$order = $Model->payDetail($data['out_trade_no'])){
- $this->returnHttpCode(false,'订单不存在');
- }
-
- //判断支付状态
- if($data['trade_state'] == 'SUCCESS') {
- if($method == 'add'){
- $Model->updatePayStatus($data['transaction_id'],$order);
- Cache::delete($data['out_trade_no']);
- }else{
- // 更新订单状态
- $order->updatePayStatus($data['transaction_id']);
- }
- // 返回状态
- $this->returnHttpCode(true);
- }
- // 返回状态
- $this->returnHttpCode(false, '支付失败');
- }
-
- /**
- * 特约商户进件
- * 频率限制:15/s
- */
- public function applyment($params)
- {
- //********************* 数据加密 *****************
-
- //管理员姓名
- if(!$result = $this->getEncrypt($params['contact_info']['contact_name'])){
- return false;
- }
- $params['contact_info']['contact_name'] = $result;
- //管理员电话
- if(!$result = $this->getEncrypt($params['contact_info']['mobile_phone'])){
- return false;
- }
- $params['contact_info']['mobile_phone'] = $result;
- //管理员邮箱
- if(!$result = $this->getEncrypt($params['contact_info']['contact_email'])){
- return false;
- }
- $params['contact_info']['contact_email'] = $result;
- //身份证姓名
- if(!$result = $this->getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_name'])){
- return false;
- }
- $params['subject_info']['identity_info']['id_card_info']['id_card_name'] = $result;
- //身份证号
- if(!$result = $this->getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_number'])){
- return false;
- }
- $params['subject_info']['identity_info']['id_card_info']['id_card_number'] = $result;
-
- //身份证居住地址
- if(!$result = $this->getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_address'])){
- return false;
- }
- $params['subject_info']['identity_info']['id_card_info']['id_card_address'] = $result;
-
-
- //银行开户名称
- if(!$result = $this->getEncrypt($params['bank_account_info']['account_name'])){
- return false;
- }
- $params['bank_account_info']['account_name'] = $result;
- //银行账号
- if(!$result = $this->getEncrypt($params['bank_account_info']['account_number'])){
- return false;
- }
- $params['bank_account_info']['account_number'] = $result;
-
- //********************* 上传图片 *****************
- //营业执照
- if(!$result = $this->upload($params['subject_info']['business_license_info']['license_copy'])){
- return false;
- }
- $params['subject_info']['business_license_info']['license_copy'] = $result;
- //身份证正面
- if(!$result = $this->upload($params['subject_info']['identity_info']['id_card_info']['id_card_copy'])){
- return false;
- }
- $params['subject_info']['identity_info']['id_card_info']['id_card_copy'] = $result;
- //身份证反面
- if(!$result = $this->upload($params['subject_info']['identity_info']['id_card_info']['id_card_national'])){
- return false;
- }
- $params['subject_info']['identity_info']['id_card_info']['id_card_national'] = $result;
- //特殊资质
- if(!$result = $this->upload($params['settlement_info']['qualifications'][0])){
- return false;
- }
- $params['settlement_info']['qualifications'][0] = $result;
- //门头照片
- if(!$result = $this->upload($params['business_info']['sales_info']['biz_store_info']['store_entrance_pic'][0])){
- return false;
- }
- $params['business_info']['sales_info']['biz_store_info']['store_entrance_pic'][0] = $result;
- //店内照片
- if(!$result = $this->upload($params['business_info']['sales_info']['biz_store_info']['indoor_pic'][0])){
- return false;
- }
- $params['business_info']['sales_info']['biz_store_info']['indoor_pic'][0] = $result;
- $params = hema_json($params);
- $url = $this->getUrl('applyment4sub/applyment/');
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params),
- 'Content-Type:application/json',
- 'Accept:application/json',
- 'User-Agent:' . $this->isp_config['mch_id'],
- 'Wechatpay-Serial:' . $this->isp_config['serial_no'],
- ];
- $result = json_decode(Http::post($url, $params,[],$headers),true);
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- return $result['applyment_id'];
- }
- /**
- * 查询申请单状态
- */
- public function queryApplyment($no,$is_applyment_id = false)
- {
- if($is_applyment_id){
- $path = 'applyment_id/' . $no;//通过申请单号查询申请状态(官方返回的编号)
- }else{
- $path = 'business_code/' . $no;//通过业务申请编号查询申请状态(第三方自定义的编号)
- }
- $url = $this->getUrl('applyment4sub/applyment/'.$path);
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'GET'),
- 'Accept:application/json',
- ];
- return $this->result(json_decode(Http::get($url, [],[],$headers),true));
- }
- /**
- * 获取平台证书列表
- */
- private function certificates($is_isp=true,$applet_id='')
- {
- $url = $this->getUrl('certificates');
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'GET','',$is_isp),
- 'Accept:application/json',
- 'User-Agent:https://zh.wikipedia.org/wiki/User_agent',
- ];
- $result = json_decode(Http::get($url,[],[],$headers),true);
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- //验证是否获取到了数据
- if(!isset($result['data']) and sizeof($result['data']) == 0){
- $this->error = '未获取到可用的平台证书';
- return false;
- }
- $result = $result['data'][0];//获取证书列表中的第一个数据
- if($is_isp){
- $api_key = $this->isp_config['api_key'];
- }else{
- $api_key = $this->config['api_key'];
- }
- if(!$decrypt = new AesUtil($api_key)){
- $this->error = $decrypt->getError();
- return false;
- }
- if(!$res = $decrypt->decryptToString($result['encrypt_certificate']['associated_data'], $result['encrypt_certificate']['nonce'], $result['encrypt_certificate']['ciphertext'])){
- $this->error = $decrypt->getError();
- return false;
- }
- //计算到期时间
- $expire_time = explode('T',$result['expire_time']);
- $expire_time = strtotime($expire_time[0]);
- $model = new Setting;
- //更新平台证书
- if($is_isp){
- $this->isp_config['certificates'] = $res;
- $this->isp_config['serial_no'] = $result['serial_no'];
- $this->isp_config['expire_time'] = $expire_time;
- $model->edit('wxpayisp',$this->isp_config,0); //保存到数据库
- return true;
- }
- //更新特约商户 平台证书
- $this->config['certificates'] = $res;
- $this->config['serial_no'] = $result['serial_no'];
- $this->config['expire_time'] = $expire_time;
- if(empty($applet_id)){
- $config = Setting::getItem('webpay',0);
- $config['wx']['certificates'] = $res;
- $config['wx']['serial_no'] = $result['serial_no'];
- $config['wx']['expire_time'] = $expire_time;
- $model->edit('webpay',$config,0); //保存到数据库
- }else{
- $model->edit('wxpay',$this->config,$applet_id); //保存到数据库
- }
- return true;
- }
-
- /**
- * 图片上传API
- */
- private function upload($file_path)
- {
- $file = file_get_contents($file_path);//获取网络图片
- //获取文件名称
- $arr = explode('/',$file_path);
- $filename = $arr[sizeof($arr)-1];
- $meta =[
- 'filename' => $filename,
- 'sha256' => hash('sha256',$file),
- ];
- $url = $this->getUrl('merchant/media/upload');
- $boundary = uniqid();//随机数
- $headers = [
- 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',hema_json($meta)),
- 'Accept:application/json',
- 'Content-Type:multipart/form-data;boundary=' . $boundary,
- ];
- $params = '--' . $boundary . "\r\n";
- $params .= 'Content-Disposition:form-data; name="meta"' . "\r\n";
- $params .= 'Content-Type:application/json' . "\r\n\r\n";
- $params .= hema_json($meta) . "\r\n";
- $params .= '--' . $boundary . "\r\n";
- $params .= 'Content-Disposition:form-data;name="file";filename="' . $meta['filename'] . '"' . "\r\n";
- $params .= 'Content-Type:image/jpg' . "\r\n\r\n";
- $params .= $file . "\r\n";
- $params .= '--' . $boundary . '--' . "\r\n";
- $result = json_decode(Http::post($url, $params,[],$headers),true);
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- if(isset($result['media_id'])){
- return $result['media_id'];
- }
- $this->error = '图片上传失败';
- return false;
- }
-
- /**
- * 调起支付签名
- */
- private function paySign($data)
- {
- $params = $this->config['app_id'] . "\n" .
- $data['timeStamp'] . "\n" .
- $data['nonceStr'] . "\n" .
- $data['package'] . "\n";
- if($this->config['is_sub'] == 1){
- //服务商
- $private_key = $this->isp_config['key_pem']; //API私有证书
- }else{
- //直连商户
- $private_key = $this->config['key_pem']; //API私有证书
- }
- $raw_sign = '';
- openssl_sign($params, $raw_sign, $private_key, 'sha256WithRSAEncryption');
- return base64_encode($raw_sign);
- }
-
- /**
- * 生成签名
- * $http_method = HTTP请求的方法(GET,POST,PUT
- * serial_no 为你的商户证书序列号
- * $mch_private_key = 是商户API私钥,在商户平台下载的证书文件包含该文件,名称为apiclient_key.pem
- * $is_isp 是否为服务商操作
- */
- private function sign($url,$http_method,$body='',$is_isp=true)
- {
- $timestamp = time(); //时间戳
- $nonce = $this->nonce(); //随机字符串
- $url_parts = parse_url($url);
- $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
- $params = $http_method . "\n" .
- $canonical_url . "\n" .
- $timestamp . "\n" .
- $nonce . "\n" .
- $body . "\n";
- if($is_isp){
- $mchid = $this->isp_config['mch_id']; //商户号
- $serial_no = $this->isp_config['api_serial_no']; //API证书序列号
- $mch_private_key = $this->isp_config['key_pem']; //API私有证书
- }else{
- $mchid = $this->config['mch_id']; //商户号
- $serial_no = $this->config['api_serial_no']; //API证书序列号
- $mch_private_key = $this->config['key_pem']; //API私有证书
- }
- $raw_sign = '';
- openssl_sign($params, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
- $sign = base64_encode($raw_sign);
- //$schema = 'WECHATPAY2-SHA256-RSA2048';
- $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',$mchid, $nonce, $timestamp, $serial_no, $sign);
- return $token;
- }
- /**
- * 敏感信息加密
- */
- private function getEncrypt($str,$is_isp = true,$applet_id='')
- {
- //判断平台证书是否过期
- if($is_isp){
- //服务商
- if($this->isp_config['expire_time'] < time()){
- //更新平台证书
- if(!$this->certificates()){
- return false;//更新失败
- }
- }
- $public_key = $this->isp_config['certificates'];//平台证书
- }else{
- //直连商户
- if($this->config['expire_time'] < time()){
- //更新平台证书
- if(!$this->certificates(false,$applet_id)){
- return false;//更新失败
- }
- }
- $public_key = $this->config['certificates'];//平台证书
- }
- $encrypted = '';
- if (!openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
- $this->error = '敏感信息加密失败';
- return false;
- }
- return base64_encode($encrypted);//base64编码
- }
- /**
- * 生成随机字符串
- */
- private function nonce()
- {
- return md5(uniqid());
- }
- /*
- * 拼接请求域名接口
- */
- private function getUrl($url)
- {
- return $this->api_url . '/' . $this->version . '/' . $url;
- }
- /**
- * 获取Headers数据
- */
- private function getHeaders()
- {
- $headers = array();
- foreach ($_SERVER as $key => $value) {
- if (substr($key, 0, 5) === 'HTTP_') {
- $key = substr($key, 5);
- $key = str_replace('_', ' ', $key);
- $key = str_replace(' ', '-', $key);
- $key = strtolower($key);
- $headers[$key] = $value;
- }
- }
- return $headers;
- }
- /**
- * 返回状态给微信服务器
- */
- private function returnHttpCode($is_success = true, $msg = '失败')
- {
- $json = hema_json([
- 'code' => $is_success ? 'SUCCESS' : 'FAIL',
- 'message' => $is_success ? '成功' : $msg,
- ]);
- if($is_success){
- header('HTTP/1.1 200 OK');
- }else{
- header('HTTP/1.1 404 Not Found');
- }
- die($json);
- }
- /**
- * 请求数据验证
- **/
- private function result($result)
- {
- if(isset($result['code'])){
- $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
- return false;
- }
- return $result;
- }
- public function getError()
- {
- return $this->error;
- }
-
- /********** V2接口 **********/
- /**
- * 付款码支付
- * $auth_code=付款码 $order_no=订单号 $openid=微信用户ID, $total_fee=支付金额, ,$attach=订单描述 $divide=是否分账
- */
- public function micropay($auth_code,$order_no, $total_fee,$profit_sharing = false,$attach = '订单支付')
- {
- // 当前时间
- $time = time();
- // 生成随机字符串
- $nonceStr = md5($time);
- // API参数
- $params = [
- 'auth_code' => $auth_code,//付款码支付
- 'attach' => $attach,
- 'nonce_str' => $nonceStr,//随机字符串
- 'body' => $attach,//商品描述
- 'out_trade_no' => $order_no,//商户订单号
- 'total_fee' => intval($total_fee * 100), // 价格:单位分
- 'spbill_create_ip' => \request()->ip(),//服务终端IP
- ];
- if($this->config['is_sub'] == 1){
- //服务商统一下单
- $values = Setting::getItem('wxpayisp',0);
- $this->config['api_key'] = $this->isp_config['api_key'];//服务商商户的密钥
- $params['appid'] = $this->isp_config['app_id'];//服务商商户的APPID
- $params['mch_id'] = $this->isp_config['mch_id'];//服务商商户号
- $params['sub_appid'] = $this->config['app_id'];//当前调起支付的小程序APPID
- $params['sub_mch_id'] = $this->config['mch_id'];//服务商分配的子商户号
- }else{
- $params['appid'] = $this->config['app_id'];//小程序ID
- $params['mch_id'] = $this->config['mch_id'];//商户号
- }
- //判断是否开启分账
- $divide = Setting::getItem('divide',0);
- if($profit_sharing or $divide['extract'] > 0){
- $params['profit_sharing'] = 'Y';//开启分账
- }
-
- // 生成签名
- $params['sign'] = $this->makeSign($params);
- $url = 'https://api.mch.weixin.qq.com/pay/micropay';// 请求API
- $result = $this->postXmlCurl($this->toXml($params), $url);
- $prepay = $this->fromXml($result);
- // 请求失败
- if ($prepay['return_code'] === 'FAIL') {
- die(hema_json(['code' => -10, 'msg' => $prepay['return_msg']]));
- }
- //判断付款码支付时,用户支付中,需要输入密码
- if ($prepay['result_code'] === 'USERPAYING') {
- return false;
- }
- if ($prepay['result_code'] === 'FAIL') {
- die(hema_json(['code' => -10, 'msg' => $prepay['err_code_des']]));
- }
- return $prepay['transaction_id'];//支付交易号
- }
-
- /**
- * 查询付款码支付结果是否成功
- */
- public function orderquery($out_trade_no)
- {
- // 当前时间
- $time = time();
- // 生成随机字符串
- $nonceStr = md5($time);
- // API参数
- $params = [
- 'out_trade_no' => $out_trade_no,
- 'nonce_str' => $nonceStr,//随机字符串
- ];
- if($this->config['is_sub'] == 1){
- //服务商统一下单
- $this->config['api_key'] = $this->isp_config['api_key'];//服务商商户的密钥
- $params['appid'] = $this->isp_config['app_id'];//服务商商户的APPID
- $params['mch_id'] = $this->isp_config['mch_id'];//服务商商户号
- $params['sub_appid'] = $this->config['app_id'];//当前调起支付的小程序APPID
- $params['sub_mch_id'] = $this->config['mch_id'];//服务商分配的子商户号
- }else{
- $params['appid'] = $this->config['app_id'];//小程序ID
- $params['mch_id'] = $this->config['mch_id'];//商户号
- }
- // 生成签名
- $params['sign'] = $this->makeSign($params);
- // 请求API
- $url = 'https://api.mch.weixin.qq.com/pay/orderquery';
- $result = $this->postXmlCurl($this->toXml($params), $url);
- $prepay = $this->fromXml($result);
- // 请求失败
- if ($prepay['return_code'] === 'SUCCESS' AND $prepay['result_code'] === 'SUCCESS') {
- return $prepay['trade_state'];
- }
- return 'ERROR';
- }
- /**
- * 输出xml字符
- */
- private function toXml($values)
- {
- if (!is_array($values)
- || count($values) <= 0
- ) {
- return false;
- }
- $xml = "";
- foreach ($values as $key => $val) {
- if (is_numeric($val)) {
- $xml .= "<" . $key . ">" . $val . "" . $key . ">";
- } else {
- $xml .= "<" . $key . ">" . $key . ">";
- }
- }
- $xml .= "";
- return $xml;
- }
- /**
- * 将xml转为array
- */
- private function fromXml($xml)
- {
- // 禁止引用外部xml实体
- libxml_disable_entity_loader(true);
- return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
- }
- /**
- * 以post方式提交xml到对应的接口url
- */
- private function postXmlCurl($xml, $url, $cert = false, $second = 30)
- {
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_TIMEOUT, $second);// 设置超时时间
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//https请求 不验证证书和host
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);//严格校验
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);// 要求结果为字符串且输出到屏幕上
- curl_setopt($ch, CURLOPT_POST, TRUE);// post提交方式
- curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
- curl_setopt($ch, CURLOPT_HEADER, FALSE);// 是否返回请求头
- //判断是否使用证书
- if($cert){
- $path = root_path() . '/extend/hema/wechat/cert/';
- file_put_contents($path . 'apiclient_cert.pem',$this->config['cert_pem']);
- file_put_contents($path . 'apiclient_key.pem',$this->config['key_pem']);
- curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
- curl_setopt($ch,CURLOPT_SSLCERT,$path . 'apiclient_cert.pem');
- curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
- curl_setopt($ch,CURLOPT_SSLKEY,$path . 'apiclient_key.pem');
- }
- $data = curl_exec($ch);// 运行curl
- curl_close($ch);
- return $data;
- }
-
- /**
- * 生成签名MD5
- */
- private function makeSign($values)
- {
- //签名步骤一:按字典序排序参数
- ksort($values);
- $string = $this->toUrlParams($values);
- //签名步骤二:在string后加入KEY
- $string = $string . '&key=' . $this->config['api_key'];
- //签名步骤三:MD5加密
- $string = md5($string);
- //签名步骤四:所有字符转为大写
- $result = strtoupper($string);
- return $result;
- }
-
- /**
- * 格式化参数格式化成url参数
- */
- private function toUrlParams($values)
- {
- $buff = '';
- foreach ($values as $k => $v) {
- if ($k != 'sign' && $v != '' && !is_array($v)) {
- $buff .= $k . '=' . $v . '&';
- }
- }
- return trim($buff, '&');
- }
+isp_config = Setting::getItem('wxpayisp',0);
+ $this->config = Setting::getItem('wxpayisp',0);
+ $this->config['is_sub'] = 2;
+ }
+
+ /********** V3接口 **********/
+
+ /**
+ * H5下单API
+ * $out_trade_no=订单号, $total=支付金额,,$attach=订单描述
+ * $profit_sharing=是否分账(有配送费要分账时传递)
+ */
+ public function h5($out_trade_no,$total,$notify_url,$attach='订单支付',$profit_sharing = false)
+ {
+ $params = [
+ 'description' => $attach,//商品描述
+ 'out_trade_no' => $out_trade_no,//商户订单号
+ 'attach' => $attach,//附加数据
+ 'notify_url' => base_url() . $notify_url, //通知地址
+ 'amount' => [
+ 'total' => intval($total * 100),//订单总金额,单位为分
+ ],
+ 'scene_info' => [
+ 'payer_client_ip' => \request()->ip(),//用户终端IP
+ ],
+ 'h5_info' => [
+ 'type' => 'Wap'
+ ]
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $params['sp_appid'] = $this->isp_config['app_id'];//服务商应用ID
+ $params['sp_mchid'] = $this->isp_config['mch_id'];//服务商商户号
+ $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
+ $params['sub_mchid'] = $this->config['mch_id'];//子商户号
+ $url = $this->getUrl('pay/partner/transactions/h5');//服务商
+ $is_isp = true;
+ }else{
+ //直连商户
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ $params['mchid'] = $this->config['mch_id'];//商户号
+ $url = $this->getUrl('pay/transactions/h5');//直连商户
+ $is_isp = false;
+ }
+ //判断是否开启分账
+ $divide = Setting::getItem('divide',0);
+ if($profit_sharing or $divide['extract'] > 0){
+ $params['settle_info']['profit_sharing'] = true; //开启分账
+ }
+ $params = hema_json($params);
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
+ ];
+ $result = json_decode(Http::post($url, $params,[],$headers),true);
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ return $result['h5_url'];
+ }
+ //扣取手续费 按照0.6%计算
+ private function serviceFee($fee)
+ {
+ return intval(($fee - ($fee * 6 / 1000)) * 100);
+ }
+ /**
+ * 分账
+ * $data:数组 =分账数据
+ * [
+ * out_order_no:第三方订单号
+ * transaction_id:微信订单号
+ * total:分账总金额
+ * ]
+ * $applet_id=小程序编号
+ * $delivery_fee=配送费分账金额
+ */
+ public function divide($data,$applet_id='',$delivery_fee=0)
+ {
+ $is_divide = false;//是否分账
+ $total = $data['total'];//分账总金额
+ $service_fee = 0;//平台分账金额(单位分)
+ $agent_fee = 0;//代理分账金额(单位分)
+ $agent_openid = '';//代理收款账号
+ //判断外卖订单是否分账配送费
+ if($delivery_fee > 0){
+ $total = $total - $delivery_fee;
+ $delivery_fee = $this->serviceFee($delivery_fee);//去掉手续费
+ $is_divide = true; //配送费大于0 开启分账
+ }
+ $divide = Setting::getItem('divide',0); //分佣参数
+ $applet = Applet::get($applet_id);//获取商家应用
+ //如果开启分佣
+ if($divide['extract'] > 0){
+ $extract = $total * $divide['extract'] / 100;//抽取金额
+ $service_fee = $this->serviceFee($extract);//去掉手续费
+ if($divide['agent_extract'] > 0){
+ //判断商家是否有代理商
+ if($applet['agent_id'] > 0){
+ if($account = DivideAccount::withoutGlobalScope()->where('applet_id',$applet_id)->find()){
+ if(!empty($account['open_id'])){
+ $agent_openid = $account['open_id'];
+ $agent_fee = $this->serviceFee($extract * $divide['agent_extract'] / 100);//去掉手续费
+ $service_fee = $service_fee - $agent_fee;
+ }
+ }
+ }
+ }
+ $is_divide = true; //开启分账
+ }
+ //判断是否要进行分账
+ if(!$is_divide){
+ $this->error = '不用分账';
+ return false;
+ }
+ //***************** 添加分账接收方 *********************//
+ $receivers = [];//收款方账号列表
+ //添加平台收佣账号
+ if(($service_fee + $delivery_fee) > 0){
+ if(!$this->addReceivers($applet_id)) {
+ $this->error = '添加平台分账接收方失败';
+ return false;
+ }
+ $webpay = Setting::getItem('webpay',0)['wx']; //平台微信支付参数
+ $receivers[] = [
+ 'type' => 'MERCHANT_ID',//分账接收方类型 MERCHANT_ID=商户号 PERSONAL_OPENID=个人openid
+ 'account' => $webpay['mch_id'],//分账接收方账号
+ 'amount' => $service_fee + $delivery_fee,//分账金额
+ 'description' => '分佣给平台',//分账描述
+ ];
+ }
+ //添加代理收佣账号
+ if($agent_fee > 0 and !empty($agent_openid)){
+ if(!$this->addReceivers($applet_id,false,$agent_openid)) {
+ $this->error = '添加代理分账接收方失败';
+ return false;
+ }
+ $receivers[] = [
+ 'type' => $this->config['is_sub'] == 1 ? 'PERSONAL_SUB_OPENID':'PERSONAL_OPENID',//分账接收方类型
+ 'account' => $agent_openid,//分账接收方账号
+ 'amount' => $agent_fee,//分账金额
+ 'description' => '分佣给代理',//分账描述
+ ];
+ }
+ //***************** 请求分账 *********************//
+ if(sizeof($receivers) == 0){
+ $this->error = '收款方账号列表为空';
+ return false;
+ }
+ if(!$this->profitSharing($data['transaction_id'],$data['out_order_no'],$receivers)) {
+ $this->error = '请求分账失败';
+ return false;
+ }
+ //***************** 添加交易记录 *********************//
+ $record_log = [];//交易流水记录
+ //是否增加平台分红记录(分佣)
+ if(($service_fee - $agent_fee) > 0){
+ $money = sprintf("%.2f",$service_fee / 100);//计算金额
+ //平台分红(分佣)记录
+ array_push($record_log,[
+ 'mode' => 40, //赠送
+ 'type' => 30, //微信
+ 'order_no' => $data['out_order_no'],
+ 'money' => $money,
+ 'remark' => '交易分佣'
+ ]);
+ //商户扣费记录
+ array_push($record_log,[
+ 'mode' => 50, //扣减
+ 'type' => 30, //微信
+ 'order_no' => $data['out_order_no'],
+ 'money' => $money,
+ 'user_id' => $applet['user_id'],
+ 'remark' => '交易服务费'
+ ]);
+ }
+ //是否增加配送费记录
+ if($delivery_fee > 0){
+ $money = sprintf("%.2f",$delivery_fee / 100);//计算金额
+ //平台收取记录
+ array_push($record_log,[
+ 'mode' => 40, //赠送
+ 'type' => 30, //微信
+ 'order_no' => $data['out_order_no'],
+ 'money' => $money,
+ 'remark' => '第三方配送费'
+ ]);
+ //商户扣费记录
+ array_push($record_log,[
+ 'mode' => 50, //扣减
+ 'type' => 30, //微信
+ 'order_no' => $data['out_order_no'],
+ 'money' => $money,
+ 'user_id' => $applet['user_id'],
+ 'remark' => '第三方配送费'
+ ]);
+ }
+ //是否增加代理分佣记录
+ if($agent_fee > 0){
+ $money = sprintf("%.2f",$agent_fee / 100);//计算金额
+ //平台收取记录
+ array_push($record_log,[
+ 'mode' => 40, //赠送
+ 'type' => 30, //微信
+ 'order_no' => $data['out_order_no'],
+ 'money' => $money,
+ 'user_id' => $applet['agent_id'],
+ 'remark' => '交易分佣'
+ ]);
+ }
+ //批量增加交易记录
+ $model = new Record;
+ if(!$model->saveAll($record_log)){
+ $this->error = '添加交易记录失败';
+ return false;
+ }
+ return true;
+ }
+ /**
+ * 请求分账API
+ */
+ private function profitSharing($transaction_id,$out_order_no,$receivers)
+ {
+ //服务商
+ $params = [
+ 'transaction_id' => $transaction_id,//微信订单号
+ 'out_order_no' => $out_order_no,//商户分账单号
+ 'receivers' => $receivers,
+ 'unfreeze_unsplit' => true,//是否解冻剩余未分资金
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $params['appid'] = $this->isp_config['app_id'];//服务商应用ID
+ $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
+ $params['sub_mchid'] = $this->config['mch_id'];//子商户号
+ $is_isp = true;
+ }else{
+ //直连商户
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ $is_isp = false;
+ }
+ $params = hema_json($params);
+ $url = $this->getUrl('profitsharing/orders');
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
+ 'Wechatpay-Serial:' . $this->isp_config['serial_no'],
+ ];
+ return $this->result(json_decode(Http::post($url, $params,[],$headers),true));
+ }
+ /**
+ * 添加分账接收方API
+ * $is_mchid = 接收方是否是商户 $account = 接收账号
+ */
+ private function addReceivers($applet_id,$is_mchid=true,$account='')
+ {
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $params['appid'] = $this->isp_config['app_id'];//服务商应用ID
+ $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
+ $params['sub_mchid'] = $this->config['mch_id'];//子商户号
+ if($is_mchid){
+ $webpay = Setting::getItem('webpay',0)['wx'];
+ $params['type'] = 'MERCHANT_ID';//分账接收方类型
+ $params['account'] = $webpay['mch_id'];//分账接收方账号
+ $params['name'] = $this->getEncrypt($webpay['name']); //(加密)分账个人接收方姓名 分账接收方类型是MERCHANT_ID时,是商户全称(必传)
+ }else{
+ $params['type'] = 'PERSONAL_SUB_OPENID';//分账接收方类型
+ $params['account'] = $account;//分账接收方账号
+ }
+ $params['relation_type'] = 'SERVICE_PROVIDER'; //与分账方的关系类型 服务商
+ $is_isp = true;
+ $serial_no = $this->isp_config['serial_no'];
+ }else{
+ //直连商户
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ if($is_mchid){
+ $webpay = Setting::getItem('webpay',0)['wx'];
+ $params['type'] = 'MERCHANT_ID';//分账接收方类型
+ $params['account'] = $webpay['mch_id'];//分账接收方账号
+ $params['name'] = $this->getEncrypt($webpay['name'],false,$applet_id); //(加密)分账个人接收方姓名 分账接收方类型是MERCHANT_ID时,是商户全称(必传)
+ }else{
+ $params['type'] = 'PERSONAL_OPENID';//分账接收方类型
+ $params['account'] = $account;//分账接收方账号
+ }
+ $params['relation_type'] = 'PARTNER'; ////与分账方的关系类型 合作伙伴
+ $is_isp = false;
+ $serial_no = $this->config['serial_no'];
+ }
+ $params = hema_json($params);
+ $url = $this->getUrl('profitsharing/receivers/add');
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
+ 'Wechatpay-Serial:' . $serial_no,
+ ];
+ return $this->result(json_decode(Http::post($url, $params,[],$headers),true));
+ }
+ /**
+ * 申请退款API
+ */
+ public function refunds($transaction_id,$out_refund_no,$refund_fee,$total_fee,$notify_url='',$reason='')
+ {
+ $params = [
+ 'transaction_id' => $transaction_id,//微信支付订单号
+ 'out_refund_no' => $out_refund_no,//退款订单号
+ 'amount' => [
+ 'refund' => intval($refund_fee * 100), // 退款金额,价格:单位分
+ 'total' => intval($total_fee * 100), // 订单金额,价格:单位分
+ 'currency' => 'CNY', //退款币种 只支持人民币:CNY
+ ],
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $params['sub_mchid'] = $this->config['mch_id'];//子商户号
+ $is_isp = true;
+ }else{
+ $is_isp = false;
+ }
+ !empty($reason) && $params['reason'] = $reason;//退款原因
+ !empty($notify_url) && $params['notify_url'] = base_url() . $notify_url; // 异步通知地址
+
+ $params = hema_json($params);
+ $url = $this->getUrl('refund/domestic/refunds');
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
+ ];
+ return $this->result(json_decode(Http::post($url, $params,[],$headers),true));
+
+ }
+ /**
+ * 退款成功异步通知
+ */
+ public function refundsNotify($Model,$applet_id='')
+ {
+ //接收微信服务器回调的数据流
+ if (!$json = file_get_contents('php://input')) {
+ $this->returnHttpCode(false);
+ }
+ // 将服务器返回的json数据转化为数组
+ $result = json_decode($json,true);
+ if(empty($applet_id)){
+ $this->config = Setting::getItem('webpay',0)['wx'];//平台商户支付参数
+ }else{
+ $this->config = Setting::getItem('wxpay',$applet_id);//商家商户支付参数
+ }
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $api_key = $this->isp_config['api_key'];
+ //判断平台证书是否过期
+ if($this->isp_config['expire_time'] < time()){
+ //更新平台证书
+ if(!$this->certificates()){
+ $this->returnHttpCode(false,$this->error);//更新失败
+ }
+ }
+ }else{
+ //直连商户
+ $api_key = $this->config['api_key'];
+ //判断平台证书是否过期
+ if($this->config['expire_time'] < time()){
+ //更新平台证书
+ if(!$this->certificates(false,$applet_id)){
+ $this->returnHttpCode(false,$this->error);//更新失败
+ }
+ }
+ }
+ if(!$decrypt = new AesUtil($api_key)){
+ $this->returnHttpCode(false,$decrypt->getError());
+ }
+ if(!$res = $decrypt->decryptToString($result['resource']['associated_data'], $result['resource']['nonce'], $result['resource']['ciphertext'])){
+ $this->returnHttpCode(false,$decrypt->getError());
+ }
+ $data = json_decode($res,true);
+ // 订单信息
+ if(!$order = $Model->refundDetail($data['out_refund_no'])){
+ $this->returnHttpCode(false,'订单不存在');
+ }
+
+ if($data['refund_status'] == 'SUCCESS') {
+ // 更新订单状态
+ $order->updateRefundStatus($data['refund_id']);
+ $this->returnHttpCode(true);// 返回状态
+ }
+ $this->returnHttpCode(false, '退款失败');
+ }
+ /**
+ * Native下单API
+ * $out_trade_no=订单号, $total=支付金额,$attach=订单描述 $profit_sharing=是否分账
+ */
+ public function native($out_trade_no,$total,$notify_url,$attach='订单支付',$profit_sharing = false)
+ {
+ $params = [
+ 'description' => $attach,//商品描述
+ 'out_trade_no' => $out_trade_no,//商户订单号
+ 'attach' => $attach,//附加数据
+ 'notify_url' => base_url() . $notify_url, //通知地址
+ 'amount' => [
+ 'total' => intval($total * 100),//订单总金额,单位为分
+ ],
+ 'scene_info' => [
+ 'payer_client_ip' => \request()->ip(),//用户终端IP
+ ],
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $params['sp_appid'] = $this->isp_config['app_id'];//服务商应用ID
+ $params['sp_mchid'] = $this->isp_config['mch_id'];//服务商商户号
+ //$params['sub_appid'] = $this->config['app_id'];//子商户应用ID
+ $params['sub_mchid'] = $this->config['mch_id'];//子商户号
+ //$params['payer']['sub_openid'] = $openid; //子用户标识Openid
+ $url = $this->getUrl('pay/partner/transactions/native');//服务商
+ $is_isp = true;
+ }else{
+ //直连商户
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ $params['mchid'] = $this->config['mch_id'];//商户号
+ $url = $this->getUrl('pay/transactions/native');//直连商户
+ $is_isp = false;
+ }
+ //判断是否开启分账
+ $divide = Setting::getItem('divide',0);
+ if($profit_sharing or $divide['extract'] > 0){
+ $params['settle_info']['profit_sharing'] = true; //开启分账
+ }
+ $params = hema_json($params);
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
+ ];
+ $result = json_decode(Http::post($url, $params,[],$headers),true);
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ if(!isset($result['code_url'])){
+ $this->error = 'Native下单接口请求失败';
+ return false;
+ }
+ return $result['code_url'];
+ }
+ /**
+ * JSAPI下单API
+ * $out_trade_no=订单号, $total=支付金额,$openid=微信用户ID, ,$attach=订单描述
+ * $profit_sharing=是否分账(有配送费要分账时传递)
+ */
+ public function jsapi($out_trade_no,$total,$openid,$notify_url,$attach='订单支付',$profit_sharing = false)
+ {
+ $params = [
+ 'description' => $attach,//商品描述
+ 'attach' => $attach,//附加数据
+ 'out_trade_no' => $out_trade_no,//商户订单号
+ 'notify_url' => base_url() . $notify_url, //通知地址
+ 'amount' => [
+ 'total' => intval($total * 100),//订单总金额,单位为分
+ ],
+ 'scene_info' => [
+ 'payer_client_ip' => \request()->ip(),//用户终端IP
+ ],
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $params['sp_appid'] = $this->isp_config['app_id'];//服务商应用ID
+ $params['sp_mchid'] = $this->isp_config['mch_id'];//服务商商户号
+ $params['sub_appid'] = $this->config['app_id'];//子商户应用ID
+ $params['sub_mchid'] = $this->config['mch_id'];//子商户号
+ $params['payer']['sub_openid'] = $openid; //子用户标识Openid
+ $url = $this->getUrl('pay/partner/transactions/jsapi');//服务商
+ $is_isp = true;
+ }else{
+ //直连商户
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ $params['mchid'] = $this->config['mch_id'];//商户号
+ $params['payer']['openid'] = $openid; //用户标识Openid
+ $url = $this->getUrl('pay/transactions/jsapi');//直连商户
+ $is_isp = false;
+ }
+ //判断是否开启分账
+ $divide = Setting::getItem('divide',0);
+ if($profit_sharing or $divide['extract'] > 0){
+ $params['settle_info']['profit_sharing'] = true; //开启分账
+ }
+ // $params = hema_json($params);
+ $params = json_encode($params);
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params,$is_isp),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $is_isp?$this->isp_config['mch_id']:$this->config['mch_id'],
+ ];
+
+
+
+ $result = json_decode(Http::post($url, $params,[],$headers),true);
+
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ if(!isset($result['prepay_id'])){
+ $this->error = 'JSAPI下单接口请求失败';
+ return false;
+ }
+ $data = [
+ 'timeStamp' => (string)time(),
+ 'nonceStr' => $this->nonce(),
+ 'package' => 'prepay_id=' . $result['prepay_id'],
+ 'signType' => 'RSA',
+ ];
+ $data['paySign'] = $this->paySign($data);
+ return $data;
+ }
+
+ /**
+ * 支付成功异步通知
+ */
+ public function notify($Model,$applet_id,$method='edit')
+ {
+
+ Log::write('机333','notice');
+
+ //接收微信服务器回调的数据流
+ if (!$json = file_get_contents('php://input')) {
+ $this->returnHttpCode(false);
+ }
+ // 将服务器返回的json数据转化为数组
+ $result = json_decode($json,true);
+
+ Log::write($json,'notice');
+
+ if(empty($applet_id)){
+ $this->config = Setting::getItem('webpay',0)['wx'];//平台商户支付参数
+ }else{
+ $this->config = Setting::getItem('wxpayisp',0);
+ }
+
+ $this->config['is_sub']=2;
+
+ if($this->config['is_sub'] == 1){
+ //服务商
+ $api_key = $this->isp_config['api_key'];
+ //判断平台证书是否过期
+ if($this->isp_config['expire_time'] < time()){
+ //更新平台证书
+ if(!$this->certificates()){
+ $this->returnHttpCode(false,$this->error);//更新失败
+ }
+ }
+ }else{
+ //直连商户
+ $api_key = $this->config['api_key'];
+ //判断平台证书是否过期
+ if($this->config['expire_time'] < time()){
+ //更新平台证书
+ if(!$this->certificates(false,$applet_id)){
+ $this->returnHttpCode(false,$this->error);//更新失败
+ }
+ }
+ }
+ if(!$decrypt = new AesUtil($api_key)){
+ $this->returnHttpCode(false,$decrypt->getError());
+ }
+ if(!$res = $decrypt->decryptToString($result['resource']['associated_data'], $result['resource']['nonce'], $result['resource']['ciphertext'])){
+ $this->returnHttpCode(false,$decrypt->getError());
+ }
+ $data = json_decode($res,true);
+ // 订单信息
+ if(!$order = $Model->payDetail($data['out_trade_no'])){
+ $this->returnHttpCode(false,'订单不存在');
+ }
+
+ //判断支付状态
+ if($data['trade_state'] == 'SUCCESS') {
+ if($method == 'add'){
+ $Model->updatePayStatus($data['transaction_id'],$order);
+ Cache::delete($data['out_trade_no']);
+ }else{
+ // 更新订单状态
+ $order->updatePayStatus($data['transaction_id']);
+ }
+ // 返回状态
+ $this->returnHttpCode(true);
+ }
+ // 返回状态
+ $this->returnHttpCode(false, '支付失败');
+ }
+
+ /**
+ * 特约商户进件
+ * 频率限制:15/s
+ */
+ public function applyment($params)
+ {
+ //********************* 数据加密 *****************
+
+ //管理员姓名
+ if(!$result = $this->getEncrypt($params['contact_info']['contact_name'])){
+ return false;
+ }
+ $params['contact_info']['contact_name'] = $result;
+ //管理员电话
+ if(!$result = $this->getEncrypt($params['contact_info']['mobile_phone'])){
+ return false;
+ }
+ $params['contact_info']['mobile_phone'] = $result;
+ //管理员邮箱
+ if(!$result = $this->getEncrypt($params['contact_info']['contact_email'])){
+ return false;
+ }
+ $params['contact_info']['contact_email'] = $result;
+ //身份证姓名
+ if(!$result = $this->getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_name'])){
+ return false;
+ }
+ $params['subject_info']['identity_info']['id_card_info']['id_card_name'] = $result;
+ //身份证号
+ if(!$result = $this->getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_number'])){
+ return false;
+ }
+ $params['subject_info']['identity_info']['id_card_info']['id_card_number'] = $result;
+
+ //身份证居住地址
+ if(!$result = $this->getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_address'])){
+ return false;
+ }
+ $params['subject_info']['identity_info']['id_card_info']['id_card_address'] = $result;
+
+
+ //银行开户名称
+ if(!$result = $this->getEncrypt($params['bank_account_info']['account_name'])){
+ return false;
+ }
+ $params['bank_account_info']['account_name'] = $result;
+ //银行账号
+ if(!$result = $this->getEncrypt($params['bank_account_info']['account_number'])){
+ return false;
+ }
+ $params['bank_account_info']['account_number'] = $result;
+
+ //********************* 上传图片 *****************
+ //营业执照
+ if(!$result = $this->upload($params['subject_info']['business_license_info']['license_copy'])){
+ return false;
+ }
+ $params['subject_info']['business_license_info']['license_copy'] = $result;
+ //身份证正面
+ if(!$result = $this->upload($params['subject_info']['identity_info']['id_card_info']['id_card_copy'])){
+ return false;
+ }
+ $params['subject_info']['identity_info']['id_card_info']['id_card_copy'] = $result;
+ //身份证反面
+ if(!$result = $this->upload($params['subject_info']['identity_info']['id_card_info']['id_card_national'])){
+ return false;
+ }
+ $params['subject_info']['identity_info']['id_card_info']['id_card_national'] = $result;
+ //特殊资质
+ if(!$result = $this->upload($params['settlement_info']['qualifications'][0])){
+ return false;
+ }
+ $params['settlement_info']['qualifications'][0] = $result;
+ //门头照片
+ if(!$result = $this->upload($params['business_info']['sales_info']['biz_store_info']['store_entrance_pic'][0])){
+ return false;
+ }
+ $params['business_info']['sales_info']['biz_store_info']['store_entrance_pic'][0] = $result;
+ //店内照片
+ if(!$result = $this->upload($params['business_info']['sales_info']['biz_store_info']['indoor_pic'][0])){
+ return false;
+ }
+ $params['business_info']['sales_info']['biz_store_info']['indoor_pic'][0] = $result;
+ $params = hema_json($params);
+ $url = $this->getUrl('applyment4sub/applyment/');
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',$params),
+ 'Content-Type:application/json',
+ 'Accept:application/json',
+ 'User-Agent:' . $this->isp_config['mch_id'],
+ 'Wechatpay-Serial:' . $this->isp_config['serial_no'],
+ ];
+ $result = json_decode(Http::post($url, $params,[],$headers),true);
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ return $result['applyment_id'];
+ }
+ /**
+ * 查询申请单状态
+ */
+ public function queryApplyment($no,$is_applyment_id = false)
+ {
+ if($is_applyment_id){
+ $path = 'applyment_id/' . $no;//通过申请单号查询申请状态(官方返回的编号)
+ }else{
+ $path = 'business_code/' . $no;//通过业务申请编号查询申请状态(第三方自定义的编号)
+ }
+ $url = $this->getUrl('applyment4sub/applyment/'.$path);
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'GET'),
+ 'Accept:application/json',
+ ];
+ return $this->result(json_decode(Http::get($url, [],[],$headers),true));
+ }
+ /**
+ * 获取平台证书列表
+ */
+ private function certificates($is_isp=true,$applet_id='')
+ {
+ $url = $this->getUrl('certificates');
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'GET','',$is_isp),
+ 'Accept:application/json',
+ 'User-Agent:https://zh.wikipedia.org/wiki/User_agent',
+ ];
+ $result = json_decode(Http::get($url,[],[],$headers),true);
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ //验证是否获取到了数据
+ if(!isset($result['data']) and sizeof($result['data']) == 0){
+ $this->error = '未获取到可用的平台证书';
+ return false;
+ }
+ $result = $result['data'][0];//获取证书列表中的第一个数据
+ if($is_isp){
+ $api_key = $this->isp_config['api_key'];
+ }else{
+ $api_key = $this->config['api_key'];
+ }
+ if(!$decrypt = new AesUtil($api_key)){
+ $this->error = $decrypt->getError();
+ return false;
+ }
+ if(!$res = $decrypt->decryptToString($result['encrypt_certificate']['associated_data'], $result['encrypt_certificate']['nonce'], $result['encrypt_certificate']['ciphertext'])){
+ $this->error = $decrypt->getError();
+ return false;
+ }
+ //计算到期时间
+ $expire_time = explode('T',$result['expire_time']);
+ $expire_time = strtotime($expire_time[0]);
+ $model = new Setting;
+ //更新平台证书
+ if($is_isp){
+ $this->isp_config['certificates'] = $res;
+ $this->isp_config['serial_no'] = $result['serial_no'];
+ $this->isp_config['expire_time'] = $expire_time;
+ $model->edit('wxpayisp',$this->isp_config,0); //保存到数据库
+ return true;
+ }
+ //更新特约商户 平台证书
+ $this->config['certificates'] = $res;
+ $this->config['serial_no'] = $result['serial_no'];
+ $this->config['expire_time'] = $expire_time;
+ if(empty($applet_id)){
+ $config = Setting::getItem('webpay',0);
+ $config['wx']['certificates'] = $res;
+ $config['wx']['serial_no'] = $result['serial_no'];
+ $config['wx']['expire_time'] = $expire_time;
+ $model->edit('webpay',$config,0); //保存到数据库
+ }else{
+ $model->edit('wxpay',$this->config,$applet_id); //保存到数据库
+ }
+ return true;
+ }
+
+ /**
+ * 图片上传API
+ */
+ private function upload($file_path)
+ {
+ $file = file_get_contents($file_path);//获取网络图片
+ //获取文件名称
+ $arr = explode('/',$file_path);
+ $filename = $arr[sizeof($arr)-1];
+ $meta =[
+ 'filename' => $filename,
+ 'sha256' => hash('sha256',$file),
+ ];
+ $url = $this->getUrl('merchant/media/upload');
+ $boundary = uniqid();//随机数
+ $headers = [
+ 'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $this->sign($url,'POST',hema_json($meta)),
+ 'Accept:application/json',
+ 'Content-Type:multipart/form-data;boundary=' . $boundary,
+ ];
+ $params = '--' . $boundary . "\r\n";
+ $params .= 'Content-Disposition:form-data; name="meta"' . "\r\n";
+ $params .= 'Content-Type:application/json' . "\r\n\r\n";
+ $params .= hema_json($meta) . "\r\n";
+ $params .= '--' . $boundary . "\r\n";
+ $params .= 'Content-Disposition:form-data;name="file";filename="' . $meta['filename'] . '"' . "\r\n";
+ $params .= 'Content-Type:image/jpg' . "\r\n\r\n";
+ $params .= $file . "\r\n";
+ $params .= '--' . $boundary . '--' . "\r\n";
+ $result = json_decode(Http::post($url, $params,[],$headers),true);
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ if(isset($result['media_id'])){
+ return $result['media_id'];
+ }
+ $this->error = '图片上传失败';
+ return false;
+ }
+
+ /**
+ * 调起支付签名
+ */
+ private function paySign($data)
+ {
+ $params = $this->config['app_id'] . "\n" .
+ $data['timeStamp'] . "\n" .
+ $data['nonceStr'] . "\n" .
+ $data['package'] . "\n";
+ /*if($this->config['is_sub'] == 1){
+ //服务商
+ }else{
+ //直连商户
+ $private_key = $this->config['key_pem']; //API私有证书
+ }*/
+ $private_key = $this->isp_config['key_pem']; //API私有证书
+
+ $raw_sign = '';
+ openssl_sign($params, $raw_sign, $private_key, 'sha256WithRSAEncryption');
+ return base64_encode($raw_sign);
+ }
+
+ /**
+ * 生成签名
+ * $http_method = HTTP请求的方法(GET,POST,PUT
+ * serial_no 为你的商户证书序列号
+ * $mch_private_key = 是商户API私钥,在商户平台下载的证书文件包含该文件,名称为apiclient_key.pem
+ * $is_isp 是否为服务商操作
+ */
+ private function sign($url,$http_method,$body='',$is_isp=true)
+ {
+ $timestamp = time(); //时间戳
+ $nonce = $this->nonce(); //随机字符串
+ $url_parts = parse_url($url);
+ $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
+ $params = $http_method . "\n" .
+ $canonical_url . "\n" .
+ $timestamp . "\n" .
+ $nonce . "\n" .
+ $body . "\n";
+ if($is_isp){
+ $mchid = $this->isp_config['mch_id']; //商户号
+ $serial_no = $this->isp_config['api_serial_no']; //API证书序列号
+ $mch_private_key = $this->isp_config['key_pem']; //API私有证书
+ }else{
+ $mchid = $this->config['mch_id']; //商户号
+ $serial_no = $this->config['api_serial_no']; //API证书序列号
+ $mch_private_key = $this->config['key_pem']; //API私有证书
+ }
+ $raw_sign = '';
+ openssl_sign($params, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
+ $sign = base64_encode($raw_sign);
+ //$schema = 'WECHATPAY2-SHA256-RSA2048';
+ $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',$mchid, $nonce, $timestamp, $serial_no, $sign);
+ return $token;
+ }
+ /**
+ * 敏感信息加密
+ */
+ private function getEncrypt($str,$is_isp = true,$applet_id='')
+ {
+ //判断平台证书是否过期
+ if($is_isp){
+ //服务商
+ if($this->isp_config['expire_time'] < time()){
+ //更新平台证书
+ if(!$this->certificates()){
+ return false;//更新失败
+ }
+ }
+ $public_key = $this->isp_config['certificates'];//平台证书
+ }else{
+ //直连商户
+ if($this->config['expire_time'] < time()){
+ //更新平台证书
+ if(!$this->certificates(false,$applet_id)){
+ return false;//更新失败
+ }
+ }
+ $public_key = $this->config['certificates'];//平台证书
+ }
+ $encrypted = '';
+ if (!openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
+ $this->error = '敏感信息加密失败';
+ return false;
+ }
+ return base64_encode($encrypted);//base64编码
+ }
+ /**
+ * 生成随机字符串
+ */
+ private function nonce()
+ {
+ return md5(uniqid());
+ }
+ /*
+ * 拼接请求域名接口
+ */
+ private function getUrl($url)
+ {
+ return $this->api_url . '/' . $this->version . '/' . $url;
+ }
+ /**
+ * 获取Headers数据
+ */
+ private function getHeaders()
+ {
+ $headers = array();
+ foreach ($_SERVER as $key => $value) {
+ if (substr($key, 0, 5) === 'HTTP_') {
+ $key = substr($key, 5);
+ $key = str_replace('_', ' ', $key);
+ $key = str_replace(' ', '-', $key);
+ $key = strtolower($key);
+ $headers[$key] = $value;
+ }
+ }
+ return $headers;
+ }
+ /**
+ * 返回状态给微信服务器
+ */
+ private function returnHttpCode($is_success = true, $msg = '失败')
+ {
+ $json = hema_json([
+ 'code' => $is_success ? 'SUCCESS' : 'FAIL',
+ 'message' => $is_success ? '成功' : $msg,
+ ]);
+ if($is_success){
+ header('HTTP/1.1 200 OK');
+ }else{
+ header('HTTP/1.1 404 Not Found');
+ }
+ die($json);
+ }
+ /**
+ * 请求数据验证
+ **/
+ private function result($result)
+ {
+ if(isset($result['code'])){
+ $this->error = 'code:' . $result['code'] . ',msg:' . $result['message'];
+ return false;
+ }
+ return $result;
+ }
+ public function getError()
+ {
+ return $this->error;
+ }
+
+ /********** V2接口 **********/
+ /**
+ * 付款码支付
+ * $auth_code=付款码 $order_no=订单号 $openid=微信用户ID, $total_fee=支付金额, ,$attach=订单描述 $divide=是否分账
+ */
+ public function micropay($auth_code,$order_no, $total_fee,$profit_sharing = false,$attach = '订单支付')
+ {
+ // 当前时间
+ $time = time();
+ // 生成随机字符串
+ $nonceStr = md5($time);
+ // API参数
+ $params = [
+ 'auth_code' => $auth_code,//付款码支付
+ 'attach' => $attach,
+ 'nonce_str' => $nonceStr,//随机字符串
+ 'body' => $attach,//商品描述
+ 'out_trade_no' => $order_no,//商户订单号
+ 'total_fee' => intval($total_fee * 100), // 价格:单位分
+ 'spbill_create_ip' => \request()->ip(),//服务终端IP
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商统一下单
+ $values = Setting::getItem('wxpayisp',0);
+ $this->config['api_key'] = $this->isp_config['api_key'];//服务商商户的密钥
+ $params['appid'] = $this->isp_config['app_id'];//服务商商户的APPID
+ $params['mch_id'] = $this->isp_config['mch_id'];//服务商商户号
+ $params['sub_appid'] = $this->config['app_id'];//当前调起支付的小程序APPID
+ $params['sub_mch_id'] = $this->config['mch_id'];//服务商分配的子商户号
+ }else{
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ $params['mch_id'] = $this->config['mch_id'];//商户号
+ }
+ //判断是否开启分账
+ $divide = Setting::getItem('divide',0);
+ if($profit_sharing or $divide['extract'] > 0){
+ $params['profit_sharing'] = 'Y';//开启分账
+ }
+
+ // 生成签名
+ $params['sign'] = $this->makeSign($params);
+ $url = 'https://api.mch.weixin.qq.com/pay/micropay';// 请求API
+ $result = $this->postXmlCurl($this->toXml($params), $url);
+ $prepay = $this->fromXml($result);
+ // 请求失败
+ if ($prepay['return_code'] === 'FAIL') {
+ die(hema_json(['code' => -10, 'msg' => $prepay['return_msg']]));
+ }
+ //判断付款码支付时,用户支付中,需要输入密码
+ if ($prepay['result_code'] === 'USERPAYING') {
+ return false;
+ }
+ if ($prepay['result_code'] === 'FAIL') {
+ die(hema_json(['code' => -10, 'msg' => $prepay['err_code_des']]));
+ }
+ return $prepay['transaction_id'];//支付交易号
+ }
+
+ /**
+ * 查询付款码支付结果是否成功
+ */
+ public function orderquery($out_trade_no)
+ {
+ // 当前时间
+ $time = time();
+ // 生成随机字符串
+ $nonceStr = md5($time);
+ // API参数
+ $params = [
+ 'out_trade_no' => $out_trade_no,
+ 'nonce_str' => $nonceStr,//随机字符串
+ ];
+ if($this->config['is_sub'] == 1){
+ //服务商统一下单
+ $this->config['api_key'] = $this->isp_config['api_key'];//服务商商户的密钥
+ $params['appid'] = $this->isp_config['app_id'];//服务商商户的APPID
+ $params['mch_id'] = $this->isp_config['mch_id'];//服务商商户号
+ $params['sub_appid'] = $this->config['app_id'];//当前调起支付的小程序APPID
+ $params['sub_mch_id'] = $this->config['mch_id'];//服务商分配的子商户号
+ }else{
+ $params['appid'] = $this->config['app_id'];//小程序ID
+ $params['mch_id'] = $this->config['mch_id'];//商户号
+ }
+ // 生成签名
+ $params['sign'] = $this->makeSign($params);
+ // 请求API
+ $url = 'https://api.mch.weixin.qq.com/pay/orderquery';
+ $result = $this->postXmlCurl($this->toXml($params), $url);
+ $prepay = $this->fromXml($result);
+ // 请求失败
+ if ($prepay['return_code'] === 'SUCCESS' AND $prepay['result_code'] === 'SUCCESS') {
+ return $prepay['trade_state'];
+ }
+ return 'ERROR';
+ }
+ /**
+ * 输出xml字符
+ */
+ private function toXml($values)
+ {
+ if (!is_array($values)
+ || count($values) <= 0
+ ) {
+ return false;
+ }
+ $xml = "";
+ foreach ($values as $key => $val) {
+ if (is_numeric($val)) {
+ $xml .= "<" . $key . ">" . $val . "" . $key . ">";
+ } else {
+ $xml .= "<" . $key . ">" . $key . ">";
+ }
+ }
+ $xml .= "";
+ return $xml;
+ }
+ /**
+ * 将xml转为array
+ */
+ private function fromXml($xml)
+ {
+ // 禁止引用外部xml实体
+ libxml_disable_entity_loader(true);
+ return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
+ }
+ /**
+ * 以post方式提交xml到对应的接口url
+ */
+ private function postXmlCurl($xml, $url, $cert = false, $second = 30)
+ {
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_TIMEOUT, $second);// 设置超时时间
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//https请求 不验证证书和host
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);//严格校验
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);// 要求结果为字符串且输出到屏幕上
+ curl_setopt($ch, CURLOPT_POST, TRUE);// post提交方式
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
+ curl_setopt($ch, CURLOPT_HEADER, FALSE);// 是否返回请求头
+ //判断是否使用证书
+ if($cert){
+ $path = root_path() . '/extend/hema/wechat/cert/';
+ file_put_contents($path . 'apiclient_cert.pem',$this->config['cert_pem']);
+ file_put_contents($path . 'apiclient_key.pem',$this->config['key_pem']);
+ curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
+ curl_setopt($ch,CURLOPT_SSLCERT,$path . 'apiclient_cert.pem');
+ curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
+ curl_setopt($ch,CURLOPT_SSLKEY,$path . 'apiclient_key.pem');
+ }
+ $data = curl_exec($ch);// 运行curl
+ curl_close($ch);
+ return $data;
+ }
+
+ /**
+ * 生成签名MD5
+ */
+ private function makeSign($values)
+ {
+ //签名步骤一:按字典序排序参数
+ ksort($values);
+ $string = $this->toUrlParams($values);
+ //签名步骤二:在string后加入KEY
+ $string = $string . '&key=' . $this->config['api_key'];
+ //签名步骤三:MD5加密
+ $string = md5($string);
+ //签名步骤四:所有字符转为大写
+ $result = strtoupper($string);
+ return $result;
+ }
+
+ /**
+ * 格式化参数格式化成url参数
+ */
+ private function toUrlParams($values)
+ {
+ $buff = '';
+ foreach ($values as $k => $v) {
+ if ($k != 'sign' && $v != '' && !is_array($v)) {
+ $buff .= $k . '=' . $v . '&';
+ }
+ }
+ return trim($buff, '&');
+ }
}
\ No newline at end of file
diff --git a/public/.well-known/acme-challenge/MSXAiMoekTBByxVW78vewFjtSHH8qZ9O0Mwdzt1_dD8 b/public/.well-known/acme-challenge/MSXAiMoekTBByxVW78vewFjtSHH8qZ9O0Mwdzt1_dD8
new file mode 100644
index 0000000..a10ad66
--- /dev/null
+++ b/public/.well-known/acme-challenge/MSXAiMoekTBByxVW78vewFjtSHH8qZ9O0Mwdzt1_dD8
@@ -0,0 +1 @@
+MSXAiMoekTBByxVW78vewFjtSHH8qZ9O0Mwdzt1_dD8.M2aqQcnvx01Y2S5zCFXJr1JyTjgYmG5xwwL0dfQzKco
\ No newline at end of file
diff --git a/public/uploads/20231201/1be072d5272f567b09e85a28953712d9.jpg b/public/uploads/20231201/1be072d5272f567b09e85a28953712d9.jpg
new file mode 100644
index 0000000..9b7834a
Binary files /dev/null and b/public/uploads/20231201/1be072d5272f567b09e85a28953712d9.jpg differ
diff --git a/runtime/admin/temp/1135d99398657c0ae566d459308e8327.php b/runtime/admin/temp/1135d99398657c0ae566d459308e8327.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/165f30f93e40130c15d885f561996cb2.php b/runtime/admin/temp/165f30f93e40130c15d885f561996cb2.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/29a1b1f477dc444c90efb32e05e28fcd.php b/runtime/admin/temp/29a1b1f477dc444c90efb32e05e28fcd.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/352d937338d3cbeaa5a6b2aef6a0495e.php b/runtime/admin/temp/352d937338d3cbeaa5a6b2aef6a0495e.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/3a0f7010e1e6219083ad8c5646d41a40.php b/runtime/admin/temp/3a0f7010e1e6219083ad8c5646d41a40.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/5c32e7932a0700ecea140e20f7bc660c.php b/runtime/admin/temp/5c32e7932a0700ecea140e20f7bc660c.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/77873608a3a896bd3d43bafe9fe9a27f.php b/runtime/admin/temp/77873608a3a896bd3d43bafe9fe9a27f.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/77d3402cf97c0a269213cffcfac5cd3c.php b/runtime/admin/temp/77d3402cf97c0a269213cffcfac5cd3c.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/871d8f9ac37b49ddb1f8892d42b0b432.php b/runtime/admin/temp/871d8f9ac37b49ddb1f8892d42b0b432.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/ce62fa7229051749de6651961ed8a08c.php b/runtime/admin/temp/ce62fa7229051749de6651961ed8a08c.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/d0998e50cb4b95fe491115d630adb4d8.php b/runtime/admin/temp/d0998e50cb4b95fe491115d630adb4d8.php
old mode 100644
new mode 100755
diff --git a/runtime/admin/temp/db3fc3ab033eae396bc223a1db61ffa3.php b/runtime/admin/temp/db3fc3ab033eae396bc223a1db61ffa3.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/log/202311/21_error.log b/runtime/applet/log/202311/21_error.log
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/0401244b90b33ea4345ab01331660c33.php b/runtime/applet/temp/0401244b90b33ea4345ab01331660c33.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/4d1c52033742f01e5be6650c8d5d5c31.php b/runtime/applet/temp/4d1c52033742f01e5be6650c8d5d5c31.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/6d4c9daa5662bf5b4314aa7ff4421e3e.php b/runtime/applet/temp/6d4c9daa5662bf5b4314aa7ff4421e3e.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/6e46255bb576ddd9bc889b5af5c6af2a.php b/runtime/applet/temp/6e46255bb576ddd9bc889b5af5c6af2a.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/77dea72f140119eec7bc249b88fb2458.php b/runtime/applet/temp/77dea72f140119eec7bc249b88fb2458.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/856c52ff20046a0878ce6c7c3f189901.php b/runtime/applet/temp/856c52ff20046a0878ce6c7c3f189901.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/8f1b83cd3dd31541f148aeee4301fb03.php b/runtime/applet/temp/8f1b83cd3dd31541f148aeee4301fb03.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/9fe3befe3ea695f4e50a001bee83c480.php b/runtime/applet/temp/9fe3befe3ea695f4e50a001bee83c480.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/d406f6394afc907afff31febc70c8935.php b/runtime/applet/temp/d406f6394afc907afff31febc70c8935.php
old mode 100644
new mode 100755
diff --git a/runtime/applet/temp/f23a297c97a3d0d4d3ea56de0ee9794f.php b/runtime/applet/temp/f23a297c97a3d0d4d3ea56de0ee9794f.php
old mode 100644
new mode 100755
diff --git a/runtime/cache/13/0fd29bc1e1c9570496921b09ae2849.php b/runtime/cache/13/0fd29bc1e1c9570496921b09ae2849.php
old mode 100644
new mode 100755
diff --git a/runtime/cache/21/413a1afbfae837472e4844bda5ddbc.php b/runtime/cache/21/413a1afbfae837472e4844bda5ddbc.php
old mode 100644
new mode 100755
diff --git a/runtime/cache/30/4fce12426ae0229ae22216efc4ea5b.php b/runtime/cache/30/4fce12426ae0229ae22216efc4ea5b.php
old mode 100644
new mode 100755
diff --git a/runtime/cache/4e/819c837d54a6ed09abc77a8560a66f.php b/runtime/cache/4e/819c837d54a6ed09abc77a8560a66f.php
old mode 100644
new mode 100755
diff --git a/runtime/cache/90/11cab08498f44656fa8e2447787b43.php b/runtime/cache/90/11cab08498f44656fa8e2447787b43.php
index 5811081..2b945a5 100644
--- a/runtime/cache/90/11cab08498f44656fa8e2447787b43.php
+++ b/runtime/cache/90/11cab08498f44656fa8e2447787b43.php
@@ -1,4 +1,55 @@
-a:0:{}
\ No newline at end of file
+a:3:{s:7:"ability";a:5:{s:3:"key";s:7:"ability";s:8:"describe";s:12:"功能设置";s:6:"values";a:6:{s:12:"applet_apply";s:1:"1";s:10:"applet_fee";s:1:"0";s:13:"applet_online";s:1:"1";s:9:"pay_apply";s:1:"1";s:7:"open_id";s:0:"";s:5:"wxmap";s:35:"OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77";}s:9:"applet_id";i:0;s:11:"update_time";i:0;}s:3:"web";a:5:{s:3:"key";s:3:"web";s:8:"describe";s:12:"站点设置";s:6:"values";a:9:{s:4:"name";s:36:"蓝色畅想网络股份有限公司";s:7:"company";s:0:"";s:7:"address";s:0:"";s:3:"icp";s:0:"";s:11:"description";s:0:"";s:8:"keywords";s:0:"";s:11:"baidu_count";s:0:"";s:2:"qq";s:0:"";s:5:"phone";s:0:"";}s:9:"applet_id";i:0;s:11:"update_time";i:0;}s:8:"wxpayisp";a:5:{s:3:"key";s:8:"wxpayisp";s:8:"describe";s:27:"微信支付服务商设置";s:6:"values";a:9:{s:6:"app_id";s:18:"wx3668302906e3894f";s:6:"mch_id";s:10:"1658128914";s:7:"api_key";s:32:"GS4fwElUx6Ys9KbFMvFlmok1zkL3UMno";s:13:"api_serial_no";s:40:"51B38FC8749949FFEC70E7CDB6D8EC7057D7B250";s:8:"cert_pem";s:1504:"-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIUUbOPyHSZSf/scOfNttjscFfXslAwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjMxMTA4MTAzMjQwWhcNMjgxMTA2MTAzMjQwWjCBhDETMBEGA1UEAwwK
+MTY1ODEyODkxNDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTAwLgYDVQQL
+DCfpu4TovpvkuIDvvIjljqbpl6jvvInpo5/lk4HmnInpmZDlhazlj7gxCzAJBgNV
+BAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKUgYnkTu2HZT/eQoYNgWLYR/L5T1HRVO4jwBhrXaWqdqBOH6Jx+
+8VNhWAwg9C6ULjYfqBRlxoyAyH/0xJeFvmbL2mohpgflRsXjSqdaBgP449M3yr2T
+D0lFlRfDRHDVCOkfzUEmpWFwytBZIjI+1t5/s5Wzz4tysHTOtmBBXhcfoLwy/gdQ
+3nv1OAlH9nf9SAo9t/iZVC47Tz3gdu2WyNHepnaExUrC8cAypL9bXtCkOVHwO+Km
+7ox5sR9lGKsQ6ArANHYmpwWXxy9iOm3TzNINnMvuJ26k4qOw69qsn+bAEBW0pe82
+14uQK1mdbFZeBl6dSqxtGg2AHUMkJlE56mECAwEAAaOBuTCBtjAJBgNVHRMEAjAA
+MAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2
+Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJD
+MDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJC
+MjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQCT
+ovV7SSKsIAmiVmf0CqmRxucNIHQDPcUuBTrHFIaQYIIOwiJd2tfzzvF8CF3EAKpD
+IkaZflQaGtYQQ81atJ8TNGzeTseS0mmjucea808bvHOFmxrMmY1D/l2NjklOEpVd
+Rhs5HMtOAc4rq6cXbSK/a/sP/Lyc1vu39/bkCDITWtH8sVAxPgZpFHPR1PXxhKwJ
+iMg70BWmzIBqIWSfB9NC0kbKOk9TjJNiZk8N+IoQaWiZY/n4X0rLNEKLernlvxBu
+O+C3u/L9W1WAZM+GXsNNnPmGSF//GHPYEGWn0nKwTm9EvHERR/QGPDhMXg4h358I
+j8bCl9IjOKZtzE1+ztVu
+-----END CERTIFICATE-----";s:7:"key_pem";s:1703:"-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQClIGJ5E7th2U/3
+kKGDYFi2Efy+U9R0VTuI8AYa12lqnagTh+icfvFTYVgMIPQulC42H6gUZcaMgMh/
+9MSXhb5my9pqIaYH5UbF40qnWgYD+OPTN8q9kw9JRZUXw0Rw1QjpH81BJqVhcMrQ
+WSIyPtbef7OVs8+LcrB0zrZgQV4XH6C8Mv4HUN579TgJR/Z3/UgKPbf4mVQuO089
+4HbtlsjR3qZ2hMVKwvHAMqS/W17QpDlR8Dvipu6MebEfZRirEOgKwDR2JqcFl8cv
+Yjpt08zSDZzL7idupOKjsOvarJ/mwBAVtKXvNteLkCtZnWxWXgZenUqsbRoNgB1D
+JCZROephAgMBAAECggEAOVfoupFOpmlYKunwHPaNeBUBB3uHMSsUNLbd995Mvnin
+kLjG3+n5lnIcqIGdKrvM3IDb1tGNROfIOR9gUhphB8PNQsQSq3VEwZ3wI/PQWPrK
+62PZpUH3sgNXBlyKXQCuSn7/wZtRHWiVFguOI5LM/ZGtZNR/w7Z9buMGVKD+stp7
+Gc4C15Vss7FVh00BLOoiyncUwkdiIGMMOfBqgCHiFrphSPIdGjzb1WqMjU/Np7N0
+dSwpg0m583u8/mBovfZ+NHe1FqtXtltzl4pYohHu9qgaPtuKdFo8z6Dh+8Y5QLip
+31TzvZFpFn5ZJNBq3WQYdARkq+ZMCue6IUznA2NTjQKBgQDSTtFqs6fHvUvSLULZ
+8w3HMAAD+3EEPQf4bjrZKpvbKyuRMdzTJzjyLFqURpYELiQ+PK3KmF3rl1X0wdby
+383pHXhUjq6GfFGiYDaf8V2HMSKwrLKj8M/CGH0Z6rScE0FFM6RoSHLfZWmoLJI7
+JoEd99ekORKWLxiXGWMClq0Z4wKBgQDJAJvePrlzsCmJN4qW73b1aW7sUPpqJz8k
+lm5Nrci5hQoTx52QKYYJw+/6hEM+z+K0j3cfMe4Q/jtRcBaCaIWBTmwK+x176NZy
+4j+FsdQsIiBJDk5igGDLnuEPONJa96MSpbIgIUqgZvJs9W/j+DTwUakmiBtmzQdC
+wHKREfTt6wKBgEBvxdpbkVyxszmChKkiv2X4XwjZUZdq27ZSj9VaKMbOQ1sJXA+W
+ROxuipJDzlMZkCFBlj4s0RoOFFgZzDI+QGjcjrHZxb+O97Q4poP7AB0cAPUA9Psm
+HYHq3unB7/SiMa1yVT1edVPdTrIodeWJtqXn+jpnAjrh0zb4oE16vS7hAoGAQCGP
+mbNNnFnChuNPtqSkwdxn5cJYg3IONXBBtUsTVg3aj0ELRqnY+FipwrZcdjgBzzZO
+/YcCvC1BY9RteiI7JmyNEFvapmQ9t930AoYgegxRXL3RyJ/JQm5oxGCOzTNhtltj
+n9i/ZLoz8wvELWpOCbckTwTyKTSVcnjQlPSzvw0CgYAQB4hoFDmyUvS1XLN92q+N
+tkJz8Dx5wpi094+tUiQj6Mpde0EuE5DdIdTEi3aixuazfqs5Fhe2ugoHk/l4bf44
+GJVyf61VD/ynOAmqhkp+wxILucu8oRLgHOKKjO9VFZ1Q+UIsMdYY/YD9oxRuFuOk
+wZYLkEEnMm3Rvn658+iG8A==
+-----END PRIVATE KEY-----";s:9:"serial_no";s:0:"";s:12:"certificates";s:0:"";s:11:"expire_time";s:1:"0";}s:9:"applet_id";i:0;s:11:"update_time";i:0;}}
\ No newline at end of file
diff --git a/runtime/cache/b4/1fbff599add95281dd146591f4da6f.php b/runtime/cache/b4/1fbff599add95281dd146591f4da6f.php
index 5811081..5fb11b1 100644
--- a/runtime/cache/b4/1fbff599add95281dd146591f4da6f.php
+++ b/runtime/cache/b4/1fbff599add95281dd146591f4da6f.php
@@ -1,4 +1,78 @@
-a:0:{}
\ No newline at end of file
+a:1:{s:5:"wxpay";a:5:{s:3:"key";s:5:"wxpay";s:8:"describe";s:12:"微信支付";s:6:"values";a:10:{s:6:"app_id";s:18:"wx3668302906e3894f";s:6:"mch_id";s:10:"1658128914";s:7:"api_key";s:32:"GS4fwElUx6Ys9KbFMvFlmok1zkL3UMno";s:13:"api_serial_no";s:40:"51B38FC8749949FFEC70E7CDB6D8EC7057D7B250";s:8:"cert_pem";s:1504:"-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIUUbOPyHSZSf/scOfNttjscFfXslAwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjMxMTA4MTAzMjQwWhcNMjgxMTA2MTAzMjQwWjCBhDETMBEGA1UEAwwK
+MTY1ODEyODkxNDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTAwLgYDVQQL
+DCfpu4TovpvkuIDvvIjljqbpl6jvvInpo5/lk4HmnInpmZDlhazlj7gxCzAJBgNV
+BAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKUgYnkTu2HZT/eQoYNgWLYR/L5T1HRVO4jwBhrXaWqdqBOH6Jx+
+8VNhWAwg9C6ULjYfqBRlxoyAyH/0xJeFvmbL2mohpgflRsXjSqdaBgP449M3yr2T
+D0lFlRfDRHDVCOkfzUEmpWFwytBZIjI+1t5/s5Wzz4tysHTOtmBBXhcfoLwy/gdQ
+3nv1OAlH9nf9SAo9t/iZVC47Tz3gdu2WyNHepnaExUrC8cAypL9bXtCkOVHwO+Km
+7ox5sR9lGKsQ6ArANHYmpwWXxy9iOm3TzNINnMvuJ26k4qOw69qsn+bAEBW0pe82
+14uQK1mdbFZeBl6dSqxtGg2AHUMkJlE56mECAwEAAaOBuTCBtjAJBgNVHRMEAjAA
+MAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2
+Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJD
+MDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJC
+MjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQCT
+ovV7SSKsIAmiVmf0CqmRxucNIHQDPcUuBTrHFIaQYIIOwiJd2tfzzvF8CF3EAKpD
+IkaZflQaGtYQQ81atJ8TNGzeTseS0mmjucea808bvHOFmxrMmY1D/l2NjklOEpVd
+Rhs5HMtOAc4rq6cXbSK/a/sP/Lyc1vu39/bkCDITWtH8sVAxPgZpFHPR1PXxhKwJ
+iMg70BWmzIBqIWSfB9NC0kbKOk9TjJNiZk8N+IoQaWiZY/n4X0rLNEKLernlvxBu
+O+C3u/L9W1WAZM+GXsNNnPmGSF//GHPYEGWn0nKwTm9EvHERR/QGPDhMXg4h358I
+j8bCl9IjOKZtzE1+ztVu
+-----END CERTIFICATE-----";s:7:"key_pem";s:1703:"-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQClIGJ5E7th2U/3
+kKGDYFi2Efy+U9R0VTuI8AYa12lqnagTh+icfvFTYVgMIPQulC42H6gUZcaMgMh/
+9MSXhb5my9pqIaYH5UbF40qnWgYD+OPTN8q9kw9JRZUXw0Rw1QjpH81BJqVhcMrQ
+WSIyPtbef7OVs8+LcrB0zrZgQV4XH6C8Mv4HUN579TgJR/Z3/UgKPbf4mVQuO089
+4HbtlsjR3qZ2hMVKwvHAMqS/W17QpDlR8Dvipu6MebEfZRirEOgKwDR2JqcFl8cv
+Yjpt08zSDZzL7idupOKjsOvarJ/mwBAVtKXvNteLkCtZnWxWXgZenUqsbRoNgB1D
+JCZROephAgMBAAECggEAOVfoupFOpmlYKunwHPaNeBUBB3uHMSsUNLbd995Mvnin
+kLjG3+n5lnIcqIGdKrvM3IDb1tGNROfIOR9gUhphB8PNQsQSq3VEwZ3wI/PQWPrK
+62PZpUH3sgNXBlyKXQCuSn7/wZtRHWiVFguOI5LM/ZGtZNR/w7Z9buMGVKD+stp7
+Gc4C15Vss7FVh00BLOoiyncUwkdiIGMMOfBqgCHiFrphSPIdGjzb1WqMjU/Np7N0
+dSwpg0m583u8/mBovfZ+NHe1FqtXtltzl4pYohHu9qgaPtuKdFo8z6Dh+8Y5QLip
+31TzvZFpFn5ZJNBq3WQYdARkq+ZMCue6IUznA2NTjQKBgQDSTtFqs6fHvUvSLULZ
+8w3HMAAD+3EEPQf4bjrZKpvbKyuRMdzTJzjyLFqURpYELiQ+PK3KmF3rl1X0wdby
+383pHXhUjq6GfFGiYDaf8V2HMSKwrLKj8M/CGH0Z6rScE0FFM6RoSHLfZWmoLJI7
+JoEd99ekORKWLxiXGWMClq0Z4wKBgQDJAJvePrlzsCmJN4qW73b1aW7sUPpqJz8k
+lm5Nrci5hQoTx52QKYYJw+/6hEM+z+K0j3cfMe4Q/jtRcBaCaIWBTmwK+x176NZy
+4j+FsdQsIiBJDk5igGDLnuEPONJa96MSpbIgIUqgZvJs9W/j+DTwUakmiBtmzQdC
+wHKREfTt6wKBgEBvxdpbkVyxszmChKkiv2X4XwjZUZdq27ZSj9VaKMbOQ1sJXA+W
+ROxuipJDzlMZkCFBlj4s0RoOFFgZzDI+QGjcjrHZxb+O97Q4poP7AB0cAPUA9Psm
+HYHq3unB7/SiMa1yVT1edVPdTrIodeWJtqXn+jpnAjrh0zb4oE16vS7hAoGAQCGP
+mbNNnFnChuNPtqSkwdxn5cJYg3IONXBBtUsTVg3aj0ELRqnY+FipwrZcdjgBzzZO
+/YcCvC1BY9RteiI7JmyNEFvapmQ9t930AoYgegxRXL3RyJ/JQm5oxGCOzTNhtltj
+n9i/ZLoz8wvELWpOCbckTwTyKTSVcnjQlPSzvw0CgYAQB4hoFDmyUvS1XLN92q+N
+tkJz8Dx5wpi094+tUiQj6Mpde0EuE5DdIdTEi3aixuazfqs5Fhe2ugoHk/l4bf44
+GJVyf61VD/ynOAmqhkp+wxILucu8oRLgHOKKjO9VFZ1Q+UIsMdYY/YD9oxRuFuOk
+wZYLkEEnMm3Rvn658+iG8A==
+-----END PRIVATE KEY-----";s:9:"serial_no";s:40:"2A61BFFACF420E57F1D73A069F2EA1C30961207A";s:12:"certificates";s:1475:"-----BEGIN CERTIFICATE-----
+MIIEFDCCAvygAwIBAgIUKmG/+s9CDlfx1zoGny6hwwlhIHowDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjMxMTA4MTAzMjM5WhcNMjgxMTA2MTAzMjM5WjBuMRgwFgYDVQQDDA9U
+ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl
+bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo
+ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDoIoi8kZC6F+pMZRYg
+n1NN1YsFtb6eEaf+kZtqjlj4Pe9DLAxegnsGMv/AAZyOK2i2Q1NCr6omH8YjKjFw
+rqRD/0mR3+cl0RfSQxTwF02phycmYF8s52RhYimYtD1/eISjBFN9GiEgci1P8uzy
+f62oVmSjJif5X4Elc/exoOWiCerYFF+5oAANoS59kkrLwHfNrFnKm8ZvkOjsEn1N
+0/GqjMXMvBMrOhCDD6jXtJRwixwIU7DXRhSKRJJnQS/1xQTA6VGDZTQzsQCm5tPW
+MSItnsOGocNBJU/ie8B3RKlrqxEhra882k59Z9k4b3fXsU5ap8JHRBhi39XnwME1
+sJW3AgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB
+kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv
+aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4
+RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0
+MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAK3O+Tjsmljv25DAsenDxq1DZLUkf0Ehy
++Y4pF9aUuf1hCZcoXgqlNdFqQvE5v6yYVcK8hpv04bkX/2ZSKvWvrmIWEn9Lb5Yu
+rAStXkMjBbNxpeK5PUrHo3n5LXEGuB0bamSD+i8PZPmRxA0M+crdJxdsM6DY3vSg
+TstrkoKrxgJKonUi3lRt3wUHWzPIfZe6icwGAUBWZ6csP2gFaVZzqIPN56+8Np2X
+2JJbdB2KwhEQXjNGx6wbB3qD505U0d7QStkdvy9EdpNlVwl4WKWERRpAsuUw3eiN
+cn+D5Xis/c7HL1qD35bCwC3xdJCL17uIiiQ8mOsXchORdCybEOW/dw==
+-----END CERTIFICATE-----";s:11:"expire_time";i:1857052800;s:6:"is_sub";i:2;}s:9:"applet_id";i:10001;s:11:"update_time";i:0;}}
\ No newline at end of file
diff --git a/runtime/cache/eb/300fe116b3568a7e80a6c2812b1a38.php b/runtime/cache/eb/300fe116b3568a7e80a6c2812b1a38.php
index 60db4cb..36fe805 100644
--- a/runtime/cache/eb/300fe116b3568a7e80a6c2812b1a38.php
+++ b/runtime/cache/eb/300fe116b3568a7e80a6c2812b1a38.php
@@ -1,4 +1,4 @@
-1700723253
\ No newline at end of file
+1701756591
\ No newline at end of file
diff --git a/runtime/index/temp/60a64cd47b22d798d9e777f4f707b2cd.php b/runtime/index/temp/60a64cd47b22d798d9e777f4f707b2cd.php
old mode 100644
new mode 100755
diff --git a/runtime/index/temp/b430673016f1b8d1351a534a69510985.php b/runtime/index/temp/b430673016f1b8d1351a534a69510985.php
old mode 100644
new mode 100755
diff --git a/runtime/index/temp/b84ab2a86a49fb8098a55f114226b794.php b/runtime/index/temp/b84ab2a86a49fb8098a55f114226b794.php
old mode 100644
new mode 100755
diff --git a/runtime/index/temp/c17836b361a86127d4c136cc0bb98e5b.php b/runtime/index/temp/c17836b361a86127d4c136cc0bb98e5b.php
old mode 100644
new mode 100755
diff --git a/runtime/session/sess_31e79552bdc9d8bfd196f0495656145c b/runtime/session/sess_31e79552bdc9d8bfd196f0495656145c
old mode 100644
new mode 100755
diff --git a/runtime/store/log/202311/21_error.log b/runtime/store/log/202311/21_error.log
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/0c8787a77f02614aefcaa341d7335ca2.php b/runtime/store/temp/0c8787a77f02614aefcaa341d7335ca2.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/10eaa1c936787f73e9ca337f946da334.php b/runtime/store/temp/10eaa1c936787f73e9ca337f946da334.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/233e0da4a493f66c5eda33831df6debb.php b/runtime/store/temp/233e0da4a493f66c5eda33831df6debb.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/32927b1e6f229976b3bfb1d748722e68.php b/runtime/store/temp/32927b1e6f229976b3bfb1d748722e68.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/39bcbcc718db9ee53e923309aaeb92b9.php b/runtime/store/temp/39bcbcc718db9ee53e923309aaeb92b9.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/409e4e4a205ca0731d204c8584cbd9de.php b/runtime/store/temp/409e4e4a205ca0731d204c8584cbd9de.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/5ba392d1c9e1e74ec22aae78b0af9092.php b/runtime/store/temp/5ba392d1c9e1e74ec22aae78b0af9092.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/5eecfbdd931a94d55dafc8f38d15c9ab.php b/runtime/store/temp/5eecfbdd931a94d55dafc8f38d15c9ab.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/6da5e1cd8c29396c8903d1413abd1e55.php b/runtime/store/temp/6da5e1cd8c29396c8903d1413abd1e55.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/8e50fcdf9dfa90740feb9f2ee72e8a28.php b/runtime/store/temp/8e50fcdf9dfa90740feb9f2ee72e8a28.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/988feca942d491d8bbd9f5550fca01cf.php b/runtime/store/temp/988feca942d491d8bbd9f5550fca01cf.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/acbc153a7dd97ab50d0d10d18165b7bc.php b/runtime/store/temp/acbc153a7dd97ab50d0d10d18165b7bc.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/ae9927b8c2651c650d93812e8343c6e9.php b/runtime/store/temp/ae9927b8c2651c650d93812e8343c6e9.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/b309110cddd7c2715b4a38353ff0bb36.php b/runtime/store/temp/b309110cddd7c2715b4a38353ff0bb36.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/b7355a86bf291b1b080d4bff48d89329.php b/runtime/store/temp/b7355a86bf291b1b080d4bff48d89329.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/c496503fb310b9f0807d3690b9becaa7.php b/runtime/store/temp/c496503fb310b9f0807d3690b9becaa7.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/c778416e005d01626bafe09f7eec06d2.php b/runtime/store/temp/c778416e005d01626bafe09f7eec06d2.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/ca970d4ab4bd1237b6f93eb72cba4306.php b/runtime/store/temp/ca970d4ab4bd1237b6f93eb72cba4306.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/d6e8468d5e2899d8e0a2a06666a55b1e.php b/runtime/store/temp/d6e8468d5e2899d8e0a2a06666a55b1e.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/d7390d1714e1d942ac842975d838ebd7.php b/runtime/store/temp/d7390d1714e1d942ac842975d838ebd7.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/f2a615aee8ef64e5e71245bee61efdcc.php b/runtime/store/temp/f2a615aee8ef64e5e71245bee61efdcc.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/f2d764740df911d8d11f8c0d29ea314f.php b/runtime/store/temp/f2d764740df911d8d11f8c0d29ea314f.php
old mode 100644
new mode 100755
diff --git a/runtime/store/temp/f5a702ff70f080324a5f05ce3e1cc418.php b/runtime/store/temp/f5a702ff70f080324a5f05ce3e1cc418.php
old mode 100644
new mode 100755
diff --git a/runtime/user/log/202311/21_error.log b/runtime/user/log/202311/21_error.log
old mode 100644
new mode 100755
diff --git a/runtime/user/temp/2d3218e5f4e26e3b8b658949082baf1f.php b/runtime/user/temp/2d3218e5f4e26e3b8b658949082baf1f.php
old mode 100644
new mode 100755
diff --git a/runtime/user/temp/7ed378d2e688fc3af98e70c4fc2797ba.php b/runtime/user/temp/7ed378d2e688fc3af98e70c4fc2797ba.php
old mode 100644
new mode 100755
diff --git a/runtime/user/temp/7eddf9dad1c49a6d7f1c63d22923ff77.php b/runtime/user/temp/7eddf9dad1c49a6d7f1c63d22923ff77.php
old mode 100644
new mode 100755
diff --git a/runtime/user/temp/874e2d7a5be2959b9dc4ef7ce6faa47b.php b/runtime/user/temp/874e2d7a5be2959b9dc4ef7ce6faa47b.php
old mode 100644
new mode 100755
diff --git a/runtime/user/temp/93ed04fe573c38439d4a42fb7d368b2f.php b/runtime/user/temp/93ed04fe573c38439d4a42fb7d368b2f.php
old mode 100644
new mode 100755
diff --git a/runtime/user/temp/afec97ae6c4cbf0aeb5fe21866576881.php b/runtime/user/temp/afec97ae6c4cbf0aeb5fe21866576881.php
old mode 100644
new mode 100755