diff --git a/niucloud/app/adminapi/controller/diy/Diy.php b/niucloud/app/adminapi/controller/diy/Diy.php index 96af6642f..4fa291d79 100644 --- a/niucloud/app/adminapi/controller/diy/Diy.php +++ b/niucloud/app/adminapi/controller/diy/Diy.php @@ -1,6 +1,6 @@ getApps()); } + + /** + * 复制模版 + * @return Response + */ + public function copy() + { + $params = $this->request->params([ + [ 'id', '' ], + ]); + $id = ( new DiyService() )->copy($params); + return success('ADD_SUCCESS', [ 'id' => $id ]); + } } diff --git a/niucloud/app/adminapi/controller/member/Address.php b/niucloud/app/adminapi/controller/member/Address.php new file mode 100644 index 000000000..b98079a7a --- /dev/null +++ b/niucloud/app/adminapi/controller/member/Address.php @@ -0,0 +1,93 @@ +request->params([ + ["member_id",""], + ]); + return success((new AddressService())->getList($data)); + } + + /** + * 会员收货地址详情 + * @param $id 会员收货地址id + * @return \think\Response + */ + public function info($id){ + $data = $this->request->params([ + ["member_id",""], + ]); + return success((new AddressService())->getInfo($id, $data)); + } + + /** + * 添加会员收货地址 + * @return \think\Response + */ + public function add(){ + $data = $this->request->params([ + ["member_id",""], + ["name",""], + ["mobile",""], + ["province_id",0], + ["city_id",0], + ["district_id",0], + ["address",""], + ["address_name", ""], + ["full_address",""], + ["lng",""], + ["lat",""], + ["is_default",0], + ]); + $id = (new AddressService())->add($data); + return success('ADD_SUCCESS', ['id' => $id]); + } + + /** + * 会员收货地址编辑 + * @param $id 会员收货地址id + * @return \think\Response + */ + public function edit($id){ + $data = $this->request->params([ + ["member_id",""], + ["name",""], + ["mobile",""], + ["province_id",0], + ["city_id",0], + ["district_id",0], + ["address",""], + ["address_name", ""], + ["full_address",""], + ["lng",""], + ["lat",""], + ["is_default",0], + ]); + (new AddressService())->edit($id, $data); + return success('EDIT_SUCCESS'); + } + +} diff --git a/niucloud/app/adminapi/controller/pay/Pay.php b/niucloud/app/adminapi/controller/pay/Pay.php index 0cb57eaf0..a6199e8ca 100644 --- a/niucloud/app/adminapi/controller/pay/Pay.php +++ b/niucloud/app/adminapi/controller/pay/Pay.php @@ -1,6 +1,6 @@ refuse($out_trade_no, $reason)); } -} + + /** + * 去支付 + * @return \think\Response + */ + public function pay() + { + + $data = $this->request->params([ + ['type', ''], + ['trade_type', ''],//业务类型 + ['trade_id', ''],//业务id + ['quit_url', ''], + ['buyer_id', ''], + ['return_url', ''], + ['voucher', ''], + ['openid', ''] + ]); + + return success('SUCCESS',(new PayService())->pay($data['type'], $data['trade_type'], $data['trade_id'], $data['return_url'], $data['quit_url'], $data['buyer_id'], $data['voucher'], $data['openid'])); + } + + /** + * 支付信息 + * @param $trade_type + * @param $trade_id + * @return \think\Response + */ + public function info($trade_type, $trade_id) + { + return success((new PayService())->getInfoByTrade($trade_type, $trade_id)); + } + + /** + * 找朋友帮忙付支付信息 + * @param $trade_type + * @param $trade_id + * @param $channel + * @return \think\Response + */ + public function friendspayInfo($trade_type, $trade_id, $channel) + { + return success(data:(new PayService())->getFriendspayInfoByTrade($trade_type, $trade_id, $channel)); + } + + /** + * 支付方式列表 + * @return \think\Response + */ + public function payTypeList() + { + return success(data:(new PayService())->getPayTypeList()); + } +} \ No newline at end of file diff --git a/niucloud/app/adminapi/controller/poster/Poster.php b/niucloud/app/adminapi/controller/poster/Poster.php new file mode 100644 index 000000000..a7823a879 --- /dev/null +++ b/niucloud/app/adminapi/controller/poster/Poster.php @@ -0,0 +1,37 @@ +request->params([ + [ 'id', 0 ], // 海报id + [ 'type', '' ], // 海报类型 + [ 'param', [] ], // 数据参数 + [ 'channel', 'h5' ], // 数据参数 + ]); + return success(data: poster(...$data)); + } + +} diff --git a/niucloud/app/adminapi/route/diy.php b/niucloud/app/adminapi/route/diy.php index 8ef020ca7..ee67f2a04 100644 --- a/niucloud/app/adminapi/route/diy.php +++ b/niucloud/app/adminapi/route/diy.php @@ -21,6 +21,7 @@ use think\facade\Route; Route::group('diy', function() { /***************************************************** 自定义页面管理 ****************************************************/ + // 自定义页面分页列表 Route::get('diy', 'diy.Diy/lists'); @@ -80,6 +81,9 @@ Route::group('diy', function() { // 获取模板页面(存在的应用插件列表) Route::get('apps', 'diy.Diy/getApps'); + // 复制模版 + Route::post('copy', 'diy.Diy/copy'); + /***************************************************** 配置相关 *****************************************************/ // 底部导航列表 diff --git a/niucloud/app/adminapi/route/member.php b/niucloud/app/adminapi/route/member.php index 7f64d1c2e..8e01bcfef 100644 --- a/niucloud/app/adminapi/route/member.php +++ b/niucloud/app/adminapi/route/member.php @@ -1,6 +1,6 @@ middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/adminapi/route/pay.php b/niucloud/app/adminapi/route/pay.php index 1e0b79999..cb897d7a2 100644 --- a/niucloud/app/adminapi/route/pay.php +++ b/niucloud/app/adminapi/route/pay.php @@ -1,6 +1,6 @@ middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/adminapi/route/sys.php b/niucloud/app/adminapi/route/sys.php index c0795dbca..fd70545cf 100644 --- a/niucloud/app/adminapi/route/sys.php +++ b/niucloud/app/adminapi/route/sys.php @@ -257,6 +257,9 @@ Route::group('sys', function() { // 自定义海报预览 Route::get('poster/preview', 'sys.Poster/preview'); + //获取海报 + Route::get('poster/generate', 'poster.Poster/poster'); + /***************************************************** 百度编辑器 ****************************************************/ // 获取百度编辑器配置 Route::get('ueditor', 'sys.Ueditor/getConfig'); diff --git a/niucloud/app/api/controller/pay/Pay.php b/niucloud/app/api/controller/pay/Pay.php index 872ef1bc6..dcda16b51 100644 --- a/niucloud/app/api/controller/pay/Pay.php +++ b/niucloud/app/api/controller/pay/Pay.php @@ -1,6 +1,6 @@ getInfoByTrade($trade_type, $trade_id)); + $data = $this->request->params([ + ['scene', ''] + ]); + return success((new PayService())->getInfoByTrade($trade_type, $trade_id, $data)); + } + + /** + * 获取找朋友帮忙付支付信息 + * @return Response + */ + public function friendspayInfo($trade_type, $trade_id) + { + return success((new PayService())->getFriendspayInfoByTrade($trade_type, $trade_id)); } /** diff --git a/niucloud/app/api/route/pay.php b/niucloud/app/api/route/pay.php index d064f24e3..aa87da01b 100644 --- a/niucloud/app/api/route/pay.php +++ b/niucloud/app/api/route/pay.php @@ -22,6 +22,14 @@ Route::any('pay/notify/:channel/:type/:action', 'pay.Pay/notify') /** * 路由 */ +Route::group('pay',function () { + //找朋友帮忙付支付信息 + Route::get('friendspay/info/:trade_type/:trade_id', 'pay.Pay/friendspayInfo'); + +})->middleware(ApiChannel::class) + ->middleware(ApiCheckToken::class) + ->middleware(ApiLog::class); + Route::group('pay',function () { //去支付 Route::post('', 'pay.Pay/pay'); @@ -33,5 +41,5 @@ Route::group('pay',function () { Route::post('close', 'pay.Pay/close'); })->middleware(ApiChannel::class) - ->middleware(ApiCheckToken::class) + ->middleware(ApiCheckToken::class, true)//表示验证登录 ->middleware(ApiLog::class); diff --git a/niucloud/app/dict/pay/PayChannelDict.php b/niucloud/app/dict/pay/PayChannelDict.php index 9a008aa8d..7e615fb38 100644 --- a/niucloud/app/dict/pay/PayChannelDict.php +++ b/niucloud/app/dict/pay/PayChannelDict.php @@ -34,11 +34,17 @@ class PayChannelDict // } // } foreach ($channel as $k => $v) { - $list[$k] = [ + $temp_pay_type = $pay_type; + $list[ $k ] = [ 'name' => $v, 'key' => $k, 'pay_type' => $pay_type ]; + // PC端暂不支持 帮付 + if ($k == ChannelDict::PC) { + unset($temp_pay_type[ PayDict::FRIENDSPAY ]); + $list[ $k ][ 'pay_type' ] = $temp_pay_type; + } } return $list; } diff --git a/niucloud/app/dict/pay/PayDict.php b/niucloud/app/dict/pay/PayDict.php index a1ced926d..eed6bf77d 100644 --- a/niucloud/app/dict/pay/PayDict.php +++ b/niucloud/app/dict/pay/PayDict.php @@ -19,7 +19,8 @@ class PayDict public const ALIPAY = 'alipay';//支付宝支付 //const UNIPAY = 'unipay';//银联 public const OFFLINEPAY = 'offlinepay';//线下支付 - public const BALANCEPAY = 'balancepay';//线下支付 + public const BALANCEPAY = 'balancepay';//余额支付 + public const FRIENDSPAY = 'friendspay';//找朋友帮忙付 public const ON = '1'; @@ -31,10 +32,12 @@ class PayDict //上传方式 视频 public const ALIPAY_ICON = self::PAY_ICON_PATH . 'alipay.png';//支付宝支付 - public const BALANCEPAY_ICON = self::PAY_ICON_PATH . 'balancepay.png';//支付宝支付 + public const BALANCEPAY_ICON = self::PAY_ICON_PATH . 'balancepay.png';//余额支付 public const OFFLINEPAY_ICON = self::PAY_ICON_PATH . 'offlinepay.png';//线下支付 + public const FRIENDSPAY_ICON = self::PAY_ICON_PATH . 'friendspay.png';//找朋友帮忙付 + //支付状态 public const STATUS_WAIT = '0';//待支付 public const STATUS_ING = '1';//支付中 @@ -53,27 +56,38 @@ class PayDict public static function getPayType(array $types = []) { $list = [ + // 微信支付 self::WECHATPAY => [ 'name' => get_lang('dict_pay.type_wechatpay'), 'key' => self::WECHATPAY, 'icon' => self::WECHATPAY_ICON, 'setting_component' => '/src/app/views/setting/components/pay-wechatpay.vue', - 'encrypt_params' => ['mch_public_cert_path', 'mch_secret_cert', 'mch_secret_key', 'wechat_public_cert_path'], - ],//微信支付 + 'encrypt_params' => [ 'mch_public_cert_path', 'mch_secret_cert', 'mch_secret_key', 'wechat_public_cert_path' ], + ], + // 支付宝支付 self::ALIPAY => [ 'name' => get_lang('dict_pay.type_alipay'), 'key' => self::ALIPAY, 'icon' => self::ALIPAY_ICON, 'setting_component' => '/src/app/views/setting/components/pay-alipay.vue', - 'encrypt_params' => ['app_secret_cert', 'app_public_cert_path', 'alipay_public_cert_path', 'alipay_root_cert_path'], - ],//支付宝支付 + 'encrypt_params' => [ 'app_secret_cert', 'app_public_cert_path', 'alipay_public_cert_path', 'alipay_root_cert_path' ], + ], + // 余额支付 self::BALANCEPAY => [ 'name' => get_lang('dict_pay.type_balancepay'), 'key' => self::BALANCEPAY, 'icon' => self::BALANCEPAY_ICON, 'setting_component' => '', - 'encrypt_params' => ['secret_key'], - ],//微信支付 + 'encrypt_params' => [ 'secret_key' ], + ], + // 找朋友帮忙付 + self::FRIENDSPAY => [ + 'name' => get_lang('dict_pay.type_friendspay'), + 'key' => self::FRIENDSPAY, + 'icon' => self::FRIENDSPAY_ICON, + 'setting_component' => '/src/app/views/setting/components/pay-friendspay.vue', + 'encrypt_params' => [], + ], ]; $list = array_merge($list, ...event('PayType')); @@ -81,7 +95,7 @@ class PayDict if (!empty($types)) { foreach ($list as $k => $v) { if (!in_array($k, $types)) { - unset($list[$k]); + unset($list[ $k ]); } } } diff --git a/niucloud/app/dict/pay/PaySceneDict.php b/niucloud/app/dict/pay/PaySceneDict.php new file mode 100644 index 000000000..11ec545fb --- /dev/null +++ b/niucloud/app/dict/pay/PaySceneDict.php @@ -0,0 +1,25 @@ + [], // [x,y]:左上,右上,右下,左下 ], ], - + 'FriendsPayMessage' => [ + 'title' => "帮付留言", + 'type' => 'text', + 'icon' => "nc-iconfont nc-icon-daifuliuyanV6xx", + 'path' => "friendspay-message", + 'uses' => 1, + 'sort' => 10006, + 'relate' => 'friendspay_message', // 关联字段,空为不处理 + 'value' => get_lang('dict_pay_config.pay_leave_message'), + 'template' => [ + "width" => 611, + "height" => 85, + "minWidth" => 120, + "minHeight" => 44, + ] + ], + 'FriendsPayMoney' => [ + 'title' => "帮付金额", + 'type' => 'text', + 'icon' => "nc-iconfont nc-icon-daifujineV6xx", + 'path' => "friendspay-money", + 'uses' => 1, + 'sort' => 10007, + 'relate' => 'friendspay_money', // 关联字段,空为不处理 + 'value' => '帮付金额', + 'template' => [ + "width" => 436, + "height" => 50, + "minWidth" => 120, + "minHeight" => 44, + ] + ], ], ], ]; diff --git a/niucloud/app/dict/poster/template.php b/niucloud/app/dict/poster/template.php new file mode 100644 index 000000000..ecc8c9d64 --- /dev/null +++ b/niucloud/app/dict/poster/template.php @@ -0,0 +1,170 @@ + "找朋友帮忙付模板", // 海报模板名称 + 'type' => 'friendspay', // 海报类型 + "data" => [ + "global" => [ + "width" => 720, + "height" => 1280, + "bgType" => "url", + "bgColor" => "#ffffff", + "bgUrl" => "static/resource/images/pay/friendspay_bg.jpg" + ], + "value" => [ + [ + "type" => "text", + "path" => "text", + "uses" => 0, + "relate" => "", + "value" => "您的帮付金额", + "id" => "wgvspr9fafk", + "componentName" => "Text", + "componentTitle" => "文本", + "width" => 518, + "height" => 48, + "minWidth" => 120, + "minHeight" => 44, + "x" => "center", + "y" => 759, + "angle" => 0, + "zIndex" => 8, + "fontFamily" => "static/font/SourceHanSansCN-Regular.ttf", + "fontSize" => 24, + "weight" => false, + "lineHeight" => 20, + "fontColor" => "#333333" + ], + [ + "type" => "text", + "path" => "friendspay-money", + "uses" => 1, + "relate" => "friendspay_money", + "value" => "¥369.00", + "id" => "2waud25nthq0", + "componentName" => "FriendsPayMoney", + "componentTitle" => "帮付金额", + "width" => 518, + "height" => 58, + "minWidth" => 120, + "minHeight" => 44, + "x" => "center", + "y" => 694, + "angle" => 0, + "zIndex" => 9, + "fontFamily" => "static/font/price.ttf", + "fontSize" => 56, + "weight" => false, + "lineHeight" => 10, + "fontColor" => "#FF4142" + ], + [ + "type" => "text", + "path" => "text", + "uses" => 0, + "relate" => "", + "value" => "长按识别二维码,帮我付款", + "id" => "639vjo8ebo40", + "componentName" => "Text", + "componentTitle" => "文本", + "width" => 518, + "height" => 59, + "minWidth" => 120, + "minHeight" => 44, + "x" => "center", + "y" => 1097, + "angle" => 0, + "zIndex" => 10, + "fontFamily" => "static/font/SourceHanSansCN-Regular.ttf", + "fontSize" => 26, + "weight" => false, + "lineHeight" => 26, + "fontColor" => "#333333" + ], + [ + "type" => "text", + "path" => "friendspay-message", + "uses" => 1, + "relate" => "friendspay_message", + "value" => "帮我付一下这笔订单吧,谢谢啦~", + "id" => "5oyikcgoylo0", + "componentName" => "FriendsPayMessage", + "componentTitle" => "帮付留言", + "width" => 600, + "height" => 48, + "minWidth" => 120, + "minHeight" => 44, + "x" => "center", + "y" => 570, + "angle" => 0, + "zIndex" => 4, + "fontFamily" => "static/font/SourceHanSansCN-Regular.ttf", + "fontSize" => 26, + "weight" => false, + "lineHeight" => 10, + "fontColor" => "#666666" + ], + [ + "type" => "qrcode", + "path" => "qrcode", + "uses" => 1, + "relate" => "url", + "value" => "", + "id" => "3m6szk6d98m0", + "componentName" => "Qrcode", + "componentTitle" => "二维码", + "width" => 214, + "height" => 214, + "minWidth" => 60, + "minHeight" => 60, + "x" => 254, + "y" => 844, + "angle" => 0, + "zIndex" => 8 + ], + [ + "type" => "text", + "path" => "nickname", + "uses" => 1, + "relate" => "nickname", + "value" => "", + "id" => "31wsjudfc7m0", + "componentName" => "NickName", + "componentTitle" => "昵称", + "width" => 600, + "height" => 40, + "minWidth" => 120, + "minHeight" => 50, + "x" => "center", + "y" => 512, + "angle" => 0, + "zIndex" => 6, + "fontFamily" => "static/font/SourceHanSansCN-Regular.ttf", + "fontSize" => 30, + "weight" => false, + "lineHeight" => 10, + "fontColor" => "#303133" + ], + [ + "type" => "image", + "path" => "headimg", + "uses" => 1, + "relate" => "headimg", + "value" => "", + "id" => "5asgzwz9f5s0", + "componentName" => "HeadImg", + "componentTitle" => "头像", + "width" => 149, + "height" => 149, + "minWidth" => 60, + "minHeight" => 60, + "x" => 286, + "y" => 344, + "angle" => 0, + "zIndex" => 7, + "shape" => "circle" + ] + ] + ] + ], +]; \ No newline at end of file diff --git a/niucloud/app/event.php b/niucloud/app/event.php index cdcd645fb..5da951a7f 100644 --- a/niucloud/app/event.php +++ b/niucloud/app/event.php @@ -92,7 +92,8 @@ $system_event = [ 'StatField' => [], // 获取海报数据 - 'GetPosterData' => [ 'app\listener\system\Poster' ] + 'GetPosterType' => [ 'app\listener\system\PosterType' ], + 'GetPosterData' => [ 'app\listener\system\Poster' ], ], 'subscribe' => [ ], diff --git a/niucloud/app/install/controller/Index.php b/niucloud/app/install/controller/Index.php index 72fef3603..1699ed19e 100644 --- a/niucloud/app/install/controller/Index.php +++ b/niucloud/app/install/controller/Index.php @@ -3,11 +3,13 @@ namespace app\install\controller; +use app\model\sys\Poster; use app\model\sys\SysUser; use app\service\admin\auth\LoginService; use app\service\admin\install\InstallSystemService; use app\service\core\addon\CoreAddonInstallService; use app\service\core\addon\CoreAddonService; +use app\service\core\poster\CorePosterService; use app\service\core\schedule\CoreScheduleInstallService; use Exception; use think\facade\Cache; @@ -327,6 +329,23 @@ class Index extends BaseInstall ]); } + // 创建默认找朋友帮忙付海报 + $poster_model = new Poster(); + $poster_count = $poster_model->where([ + [ 'type', '=', 'friendspay' ] + ])->count(); + if ($poster_count == 0) { + $poster = new CorePosterService(); + $template = $poster->getTemplateList('', 'friendspay')[ 0 ]; + $poster->add('', [ + 'name' => $template[ 'name' ], + 'type' => $template[ 'type' ], + 'value' => $template[ 'data' ], + 'status' => 1, + 'is_default' => 1 + ]); + } + // 安装插件 $this->installAddon(); diff --git a/niucloud/app/install/source/database.sql b/niucloud/app/install/source/database.sql index 082906bb5..1c4200d40 100644 --- a/niucloud/app/install/source/database.sql +++ b/niucloud/app/install/source/database.sql @@ -378,6 +378,7 @@ DROP TABLE IF EXISTS `pay`; CREATE TABLE `pay` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `main_id` int(11) NOT NULL DEFAULT 0 COMMENT '支付会员id', + `from_main_id` INT(11) NOT NULL DEFAULT 0 COMMENT '发起支付会员id', `out_trade_no` varchar(255) NOT NULL DEFAULT '' COMMENT '支付流水号', `trade_type` varchar(255) NOT NULL DEFAULT '' COMMENT '业务类型', `trade_id` int(11) NOT NULL DEFAULT 0 COMMENT '业务id', diff --git a/niucloud/app/lang/zh-cn/api.php b/niucloud/app/lang/zh-cn/api.php index c933c369b..3d42e3316 100644 --- a/niucloud/app/lang/zh-cn/api.php +++ b/niucloud/app/lang/zh-cn/api.php @@ -162,6 +162,9 @@ return [ 'LEVEL_NOT_ALLOWED_DELETE' => '该等级下存在会员不允许删除', 'MEMBER_LEVEL_MAX' => '最多只能有十个等级', + // 地址相关 + 'ADDRESS_ANALYSIS_ERROR' => '地址解析异常', + //会员提现 'CASHOUT_NOT_OPEN' => '会员提现业务未开启', 'CASHOUT_TYPE_NOT_OPEN' => '当前会员提现方式未启用', @@ -176,6 +179,8 @@ return [ 'MEMBER_CASHOUT_TRANSFER' => '会员提现转账', 'CASH_OUT_ACCOUNT_NOT_EXIST' => '提现账户不存在', + //DIY + 'PAGE_NOT_EXIST' => '页面不存在', //渠道相关 占用 4****** //微信 @@ -223,6 +228,8 @@ return [ 'VOUCHER_NOT_EMPTY' => '支付单据不能为空', 'ONLY_PAYING_CAN_AUDIT' => '只有待支付的订单才可以操作', 'ONLY_OFFLINEPAY_CAN_AUDIT' => '只有线下支付的单据才可以审核', + 'TRADE_NOT_EXIST' => '支付单据不存在', + 'PAY_NOT_FOUND_TRADE' => '找不到可支付的交易', //退款相关 'REFUND_NOT_EXIST' => '退款单据不存在', //订单相关 8*** diff --git a/niucloud/app/lang/zh-cn/dict.php b/niucloud/app/lang/zh-cn/dict.php index 3e23a58b5..18f9ef249 100644 --- a/niucloud/app/lang/zh-cn/dict.php +++ b/niucloud/app/lang/zh-cn/dict.php @@ -38,6 +38,18 @@ return [ 'status_off' => '停用' ], // 站点 + 'dict_site' => [ + //站点类型 + 'type_cms' => 'cms', + 'status_on' => '正常', + 'status_experience' => '体验期', + 'status_expire' => '已到期', + 'status_close' => '已停止', + 'pay' => '支付', + 'refund' => '退款', + 'transfer' => '转账', + ], + // 站点 'dict_site_index' => [ //站点类型 'system' => '框架首页', @@ -165,6 +177,7 @@ return [ 'type_unipay' => '银联支付', 'type_offline' => '线下支付', 'type_balancepay' => '余额支付', + 'type_friendspay' => '找朋友帮忙付', 'status_wait' => '待支付', 'status_ing' => '支付中', @@ -175,6 +188,14 @@ return [ 'refund' => '退款', 'transfer' => '转账', ], + //支付配置相关 + 'dict_pay_config' => [ + 'pay_leave_message' => '帮我付一下这笔订单吧,谢谢啦~', + 'pay_button_name' => '慷慨付款', + 'pay_page_name' => '帮我付款', + 'pay_explain_title' => '帮付说明', + 'pay_explain_content' => "1.付款前请务必和好友进行确认,以避免给你造成损失。\n2.当帮付订单退款成功后,实付金额将原路退还到帮付人账户。\n3.帮付订单信息中显示的金额为单价,但因优惠活动等因素,实付金额可能会发生变化,具体金额以页面显示为准。", + ], //转账相关 'dict_transfer' => [ 'type_wechat' => '微信', @@ -227,11 +248,6 @@ return [ 'member_verify_index' => '核销台', 'member_contact' => '客服', - 'system_web_index' => '系统首页', - 'auth_login' => '登录', - 'auth_register' => '注册', - 'auth_bind' => '手机号绑定', - 'diy_page' => '自定义页面', 'diy_link' => '自定义链接', 'diy_jump_other_applet' => '小程序跳转', diff --git a/niucloud/app/listener/poster/FriendspayPoster.php b/niucloud/app/listener/poster/FriendspayPoster.php new file mode 100644 index 000000000..d1cf05c5e --- /dev/null +++ b/niucloud/app/listener/poster/FriendspayPoster.php @@ -0,0 +1,100 @@ + 'id', 'value' => $trade_id ], + [ 'key' => 'type', 'value' => $trade_type ] + ]; + + if ($mode == 'preview') { + // 预览模式 + $return_data = [ + 'nickname' => '会员昵称的帮付', + 'headimg' => 'static/resource/images/default_headimg.png', + 'friendspay_message' => get_lang('dict_pay_config.pay_leave_message'), + 'friendspay_money' => '¥369.00', + 'url' => [ + 'url' => ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ], + 'page' => 'app/pages/friendspay/money', + 'data' => $url_data, + ], + ]; + return $return_data; + } + + $pay_info = ( new Pay() )->field('money')->where([ + [ 'trade_id', '=', $trade_id ], + [ 'trade_type', '=', $trade_type ], + [ 'status', '<>', PayDict::STATUS_CANCLE ],///不查询已取消的单据 + ])->findOrEmpty()->toArray(); + + if (empty($pay_info)) return []; + + $member_info = []; + + if ($member_id > 0) { + //查询会员信息 + $member_info = ( new Member() )->where([ [ 'member_id', '=', $member_id ] ])->findOrEmpty(); + + if (!empty($member_info)) { + if (empty($member_info[ 'headimg' ])) { + $member_info[ 'headimg' ] = 'static/resource/images/default_headimg.png'; + } + } + } + + $pay_config = []; + $pay_type_list = ( new CorePayChannelService() )->getAllowPayTypeByChannel($channel, $trade_type); + if (!empty($pay_type_list) && !empty($pay_type_list[ PayDict::FRIENDSPAY ])) { + $pay_config = $pay_type_list[ PayDict::FRIENDSPAY ][ 'config' ]; + } + + $return_data = [ + 'friendspay_message' => $pay_config[ 'pay_leave_message' ] ?? get_lang('dict_pay_config.pay_leave_message'), + 'friendspay_money' => '¥' . $pay_info[ 'money' ], + 'url' => [ + 'url' => ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ], + 'page' => 'app/pages/friendspay/money', + 'data' => $url_data, + ], + ]; + + if (!empty($member_info)) { + $return_data[ 'nickname' ] = mb_strlen($member_info[ 'nickname' ]) > 12 ? mb_substr($member_info[ 'nickname' ], 0, 12, 'utf-8') . '...的帮付' : $member_info[ 'nickname' ] . '的帮付'; + $return_data[ 'headimg' ] = $member_info[ 'headimg' ]; + } + return $return_data; + } + } +} diff --git a/niucloud/app/listener/system/Poster.php b/niucloud/app/listener/system/Poster.php index 3808a8d82..c586478e1 100644 --- a/niucloud/app/listener/system/Poster.php +++ b/niucloud/app/listener/system/Poster.php @@ -4,6 +4,7 @@ declare ( strict_types = 1 ); namespace app\listener\system; +use app\listener\poster\FriendspayPoster; use app\model\member\Member; /** @@ -18,32 +19,39 @@ class Poster */ public function handle($data) { + $type = $data[ 'type' ] ?? ''; + switch ($type) { + case 'friendspay':// 找朋友帮忙付海报 + return ( new FriendspayPoster() )->handle($data); + break; + default: + $param = $data[ 'param' ]; + $member_id = $param[ 'member_id' ] ?? 0; - $param = $data[ 'param' ]; - $member_id = $param[ 'member_id' ] ?? 0; + $member_model = new Member(); + $member_info = $member_model->where([ + [ 'member_id', '=', $member_id ] + ])->field('nickname,headimg')->findOrEmpty()->toArray(); - $member_model = new Member(); - $member_info = $member_model->where([ - [ 'member_id', '=', $member_id ] - ])->field('nickname,headimg')->findOrEmpty()->toArray(); + if (empty($member_info)) { + return []; + } - if (empty($member_info)) { - return []; + $nickname = $member_info[ 'nickname' ]; + if (mb_strlen($nickname, 'UTF-8') > 10) { + $nickname = mb_strlen($nickname) > 10 ? mb_substr($nickname, 0, 7, 'UTF-8') . '...' : $nickname; + } + + $headimg = $member_info[ 'headimg' ]; + if (empty($headimg)) { + $headimg = 'static/resource/images/default_headimg.png'; + } + $return_data = [ + 'nickname' => $nickname, + 'headimg' => $headimg, + ]; + return $return_data; + break; } - - $nickname = $member_info[ 'nickname' ]; - if (mb_strlen($nickname, 'UTF-8') > 10) { - $nickname = mb_strlen($nickname) > 10 ? mb_substr($nickname, 0, 7, 'UTF-8') . '...' : $nickname; - } - - $headimg = $member_info[ 'headimg' ]; - if (empty($headimg)) { - $headimg = 'static/resource/images/default_headimg.png'; - } - $return_data = [ - 'nickname' => $nickname, - 'headimg' => $headimg, - ]; - return $return_data; } } diff --git a/niucloud/app/listener/system/PosterType.php b/niucloud/app/listener/system/PosterType.php new file mode 100644 index 000000000..0cd5ba7b1 --- /dev/null +++ b/niucloud/app/listener/system/PosterType.php @@ -0,0 +1,30 @@ + 'friendspay', + 'addon' => '', + 'name' => '找朋友帮忙付海报', + 'decs' => '找朋友帮忙付,分享后进入帮付页面', + 'icon' => 'static/resource/images/poster/type_friendspay.png' + ], + ]; + + } +} diff --git a/niucloud/app/service/admin/diy/DiyService.php b/niucloud/app/service/admin/diy/DiyService.php index e2669ee2c..d413d361a 100644 --- a/niucloud/app/service/admin/diy/DiyService.php +++ b/niucloud/app/service/admin/diy/DiyService.php @@ -647,4 +647,27 @@ class DiyService extends BaseAdminService } } } + + /** + * 复制自定义页面 + * @param array $param + * @return mixed + */ + public function copy($param) + { + $info = $this->model->where([ [ 'id', '=', $param[ 'id' ] ] ])->findOrEmpty()->toArray(); + if (empty($info)) throw new AdminException('PAGE_NOT_EXIST'); + + unset($info[ 'id' ]); + $info[ 'page_title' ] = $info[ 'page_title' ] . '_副本'; + $info[ 'is_default' ] = 0; + $info[ 'is_change' ] = 0; + $info[ 'share' ] = ''; + $info[ 'create_time' ] = time(); + $info[ 'update_time' ] = time(); + + $res = $this->model->create($info); + return $res->id; + } + } diff --git a/niucloud/app/service/admin/member/AddressService.php b/niucloud/app/service/admin/member/AddressService.php new file mode 100644 index 000000000..392ebe0f8 --- /dev/null +++ b/niucloud/app/service/admin/member/AddressService.php @@ -0,0 +1,84 @@ +model = new MemberAddress(); + } + + /** + * 获取会员收货地址列表 + * @param array $where + * @return array + */ + public function getList(array $where = []) + { + return ( new CoreMemberAddressService() )->getList($where); + } + + /** + * 获取会员收货地址信息 + * @param int $id + * @param array $data + * @return array + */ + public function getInfo($id, $data) + { + return ( new CoreMemberAddressService() )->getInfo($id, $data); + } + + /** + * 添加会员收货地址 + * @param array $data + * @return mixed + */ + public function add(array $data) + { + $analysis_res = ( new AreaService() )->getAddress($data['full_address']); + if ($analysis_res['status'] == 0 && $analysis_res['message'] == 'Success' && !empty($analysis_res['result'])) { + $data['lng'] = $analysis_res['result']['location']['lng']; + $data['lat'] = $analysis_res['result']['location']['lat']; + } + return ( new CoreMemberAddressService() )->add($data); + } + + /** + * 会员收货地址编辑 + * @param int $id + * @param array $data + * @return bool + */ + public function edit(int $id, array $data) + { + $analysis_res = ( new AreaService() )->getAddress($data['full_address']); + if ($analysis_res['status'] == 0 && $analysis_res['message'] == 'Success' && !empty($analysis_res['result'])) { + $data['lng'] = $analysis_res['result']['location']['lng']; + $data['lat'] = $analysis_res['result']['location']['lat']; + } + return ( new CoreMemberAddressService() )->edit($id, $data); + } + +} diff --git a/niucloud/app/service/admin/pay/PayChannelService.php b/niucloud/app/service/admin/pay/PayChannelService.php index 25c554987..6a9dc3d96 100644 --- a/niucloud/app/service/admin/pay/PayChannelService.php +++ b/niucloud/app/service/admin/pay/PayChannelService.php @@ -107,11 +107,14 @@ class PayChannelService extends BaseAdminService if ($config_v !== '' && in_array($config_k, $encrypt_params)) $temp_v_item['config'][$config_k] = CommonDict::ENCRYPT_STR; } } else { - $temp_v_item = [ 'status' => 0, 'config' => [ 'name' => '' ], 'sort' => 0 ]; + $temp_v_item = [ 'status' => 0, 'config' => $this->getConfigByPayType([], $item_k), 'sort' => 0 ]; } $item_v[ 'config' ] = $temp_v_item[ 'config' ]; $item_v[ 'status' ] = $temp_v_item[ 'status' ]; $item_v[ 'sort' ] = $temp_v_item[ 'sort' ]; + if ($item_k == PayDict::FRIENDSPAY) { + $item_v[ 'name' ] = $temp_v_item[ 'config' ][ 'pay_type_name' ] ?? get_lang('dict_pay.type_friendspay'); + } $channel_list[ $k ][ 'pay_type' ][ $item_k ] = $item_v; } $temp_pay_type = array_values($channel_list[ $k ][ 'pay_type' ]); @@ -185,6 +188,18 @@ class PayChannelService extends BaseAdminService 'collection_desc' => $data[ 'collection_desc' ] ?? '',// 必填-转账说明 ]; break; + case PayDict::FRIENDSPAY: + $config = [ + 'pay_type_name' => $data[ 'pay_type_name' ] ?? get_lang('dict_pay.type_friendspay'),// 支付方式名称 + 'pay_leave_message' => $data[ 'pay_leave_message' ] ?? get_lang('dict_pay_config.pay_leave_message'),// 发起帮付默认留言 + 'pay_button_name' => $data[ 'pay_button_name' ] ?? get_lang('dict_pay_config.pay_button_name'),// 支付按钮名称 + 'pay_page_name' => $data[ 'pay_page_name' ] ?? get_lang('dict_pay_config.pay_page_name'),// 帮付页面名称 + 'pay_explain_switch' => $data[ 'pay_explain_switch' ] ?? 1,// 帮付说明开关, 1开启,0关闭 + 'pay_explain_title' => $data[ 'pay_explain_title' ] ?? get_lang('dict_pay_config.pay_explain_title'),// 帮付说明标题 + 'pay_explain_content' => $data[ 'pay_explain_content' ] ?? get_lang('dict_pay_config.pay_explain_content'),// 帮付说明内容 + 'pay_info_switch' => $data[ 'pay_info_switch' ] ?? 1,// 订单信息, 1开启,0关闭 + ]; + break; default: $config = $data; } diff --git a/niucloud/app/service/admin/pay/PayService.php b/niucloud/app/service/admin/pay/PayService.php index a6cda3043..f157f87c9 100644 --- a/niucloud/app/service/admin/pay/PayService.php +++ b/niucloud/app/service/admin/pay/PayService.php @@ -1,6 +1,6 @@ model->where([ ['type', '=', PayDict::OFFLINEPAY] ])->withSearch([ 'create_time', 'out_trade_no', 'status' ], $where)->field($field)->append([ 'type_name' ])->order('create_time desc'); + $search_model = $this->model->where([ [ 'type', '=', PayDict::OFFLINEPAY ] ])->withSearch([ 'create_time', 'out_trade_no', 'status' ], $where)->field($field)->append([ 'type_name' ])->order('create_time desc'); return $this->pageQuery($search_model); } @@ -44,9 +55,10 @@ class PayService extends BaseAdminService * @param int $id * @return void */ - public function getDetail(int $id){ + public function getDetail(int $id) + { $field = 'id,out_trade_no,trade_type,trade_id,trade_no,body,money,voucher,status,create_time,pay_time,cancel_time,type,channel,fail_reason'; - return $this->model->where([ ['id', '=', $id ] ]) + return $this->model->where([ [ 'id', '=', $id ] ]) ->field($field) ->append([ 'type_name', 'channel_name', 'status_name' ]) ->findOrEmpty() @@ -58,8 +70,9 @@ class PayService extends BaseAdminService * @param string $out_trade_no * @return null */ - public function pass(string $out_trade_no) { - return (new CoreOfflineService())->pass($out_trade_no); + public function pass(string $out_trade_no) + { + return ( new CoreOfflineService() )->pass($out_trade_no); } /** @@ -67,8 +80,9 @@ class PayService extends BaseAdminService * @param string $out_trade_no * @param string $reason */ - public function refuse(string $out_trade_no, string $reason) { - return (new CoreOfflineService())->refuse($out_trade_no, $reason); + public function refuse(string $out_trade_no, string $reason) + { + return ( new CoreOfflineService() )->refuse($out_trade_no, $reason); } /** @@ -81,4 +95,129 @@ class PayService extends BaseAdminService { return $this->model->where($where)->count(); } + + /** + * 去支付 + * @param string $type + * @param string $trade_type + * @param int $trade_id + * @param string $return_url + * @param string $quit_url + * @param string $buyer_id + * @return mixed + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function pay(string $type, string $trade_type, int $trade_id, string $return_url = '', string $quit_url = '', string $buyer_id = '', string $voucher = '', string $openid = '') + { + return ( new CorePayService() )->pay($trade_type, $trade_id, $type, ChannelDict::PC, $openid, $return_url, $quit_url, $buyer_id, $voucher); + } + + /** + * 获取支付信息 + * @param string $trade_type + * @param int $trade_id + * @return array + */ + public function getInfoByTrade(string $trade_type, int $trade_id) + { + return ( new CorePayService() )->getInfoByTrade($trade_type, $trade_id, ChannelDict::H5); + } + + /** + * 获取找朋友帮忙付支付信息 + * @param string $trade_type + * @param int $trade_id + * @return array + */ + public function getFriendspayInfoByTrade(string $trade_type, int $trade_id, string $channel) + { + $pay_info = ( new CorePayService() )->getInfoByTrade($trade_type, $trade_id, ChannelDict::H5, PaySceneDict::FRIENDSPAY); + if (!empty($pay_info)) { + //海报 + $poster = ( new Poster() )->field('id')->where([ + [ 'type', '=', 'friendspay' ], + [ 'status', '=', 1 ], + [ 'is_default', '=', 1 ] + ])->findOrEmpty()->toArray(); + if (!empty($poster)) { + $pay_info[ 'poster_id' ] = $poster[ 'id' ]; + } + //发起帮付会员信息 + $member = ( new Member() )->field('member_id,nickname,headimg')->where([ + [ 'member_id', '=', $pay_info[ 'from_main_id' ] ] + ])->findOrEmpty()->toArray(); + $pay_info[ 'member' ] = $member; + //二维码 + $qrcode = $this->getQrcode($trade_type, $trade_id, $channel); + $pay_info[ 'link' ] = $qrcode[ 'url' ]; + $pay_info[ 'qrcode' ] = $qrcode[ 'path' ]; + } + return $pay_info; + } + + /** + * 获取找朋友帮忙付二维码 + * @param string $trade_type + * @param int $trade_id + * @return array + */ + public function getQrcode(string $trade_type, int $trade_id, string $channel) + { + $url = ( new CoreSysConfigService() )->getSceneDomain()[ 'wap_url' ]; + $page = 'app/pages/friendspay/money'; + + $data = [ + [ + 'key' => 'id', + 'value' => $trade_id + ], + [ + 'key' => 'type', + 'value' => $trade_type + ] + ]; + $dir = 'upload/friendspay_qrcode'; + + $path = ''; + try { + $path = qrcode($url, $page, $data, $dir, $channel); + } catch (\Exception $e) { + Log::write('找朋友帮忙付二维码生成error' . $e->getMessage() . $e->getFile() . $e->getLine()); + } + + $url = $url . '/' . $page; + $scene = []; + foreach ($data as $v) { + $scene[] = $v[ 'key' ] . '=' . $v[ 'value' ]; + } + $url .= '?' . implode('&', $scene); + + return [ + 'url' => $url, + 'path' => $path + ]; + } + + /** + * 获取支付方式列表 + * @return array|array[] + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function getPayTypeList() + { + $pay_type_list = ( new CorePayService() )->getPayTypeByTrade('', ChannelDict::H5); + if (!empty($pay_type_list)) { + foreach ($pay_type_list as $k => $v) { + if (!in_array($v['key'], [ PayDict::BALANCEPAY, PayDict::FRIENDSPAY ])) { + unset($pay_type_list[ $k ]); + } + } + $pay_type_list = array_values($pay_type_list); + } + return $pay_type_list; + } } diff --git a/niucloud/app/service/admin/sys/AreaService.php b/niucloud/app/service/admin/sys/AreaService.php index ca66939b6..167b20631 100644 --- a/niucloud/app/service/admin/sys/AreaService.php +++ b/niucloud/app/service/admin/sys/AreaService.php @@ -87,7 +87,9 @@ class AreaService extends BaseAdminService while ($area['level'] > 1) { $area = $this->model->where([ ['id', '=', $area['pid'] ] ])->field('id,level,pid,name')->findOrEmpty(); - $tree[ $level[ $area['level'] ] ] = $area->toArray(); + if (!$area->isEmpty()) { + $tree[ $level[ $area[ 'level' ] ] ] = $area->toArray(); + } } } return $tree; diff --git a/niucloud/app/service/api/member/AddressService.php b/niucloud/app/service/api/member/AddressService.php index 3960bc589..a237911ca 100644 --- a/niucloud/app/service/api/member/AddressService.php +++ b/niucloud/app/service/api/member/AddressService.php @@ -12,6 +12,7 @@ namespace app\service\api\member; use app\model\member\MemberAddress; +use app\service\core\member\CoreMemberAddressService; use core\base\BaseApiService; @@ -35,11 +36,8 @@ class AddressService extends BaseApiService */ public function getList(array $where = []) { - $field = 'id, member_id, name, mobile, province_id, city_id, district_id, address, address_name, full_address, lng, lat, is_default'; - $order = 'is_default desc, id desc'; - - $list = $this->model->where([ ['member_id', '=', $this->member_id ] ])->field($field)->order($order)->select()->toArray(); - return $list; + $where['member_id'] = $this->member_id; + return ( new CoreMemberAddressService() )->getList($where); } /** @@ -49,10 +47,8 @@ class AddressService extends BaseApiService */ public function getInfo(int $id) { - $field = 'id,member_id,name,mobile,province_id,city_id,district_id,address,address_name,full_address,lng,lat,is_default'; - - $info = $this->model->field($field)->where([ ['id', '=', $id], ['member_id', '=', $this->member_id ] ])->findOrEmpty()->toArray(); - return $info; + $data['member_id'] = $this->member_id; + return ( new CoreMemberAddressService() )->getInfo($id, $data); } /** @@ -62,12 +58,8 @@ class AddressService extends BaseApiService */ public function add(array $data) { - if ($data['is_default']) { - $this->model->where([ ['member_id', '=', $this->member_id ] ])->update(['is_default' => 0]); - } $data['member_id'] = $this->member_id; - $res = $this->model->create($data); - return $res->id; + return ( new CoreMemberAddressService() )->add($data); } /** @@ -78,11 +70,8 @@ class AddressService extends BaseApiService */ public function edit(int $id, array $data) { - if ($data['is_default']) { - $this->model->where([ ['member_id', '=', $this->member_id ] ])->update(['is_default' => 0]); - } - $this->model->where([ ['id', '=', $id], ['member_id', '=', $this->member_id ] ])->update($data); - return true; + $data['member_id'] = $this->member_id; + return ( new CoreMemberAddressService() )->edit($id, $data); } /** diff --git a/niucloud/app/service/api/pay/PayService.php b/niucloud/app/service/api/pay/PayService.php index 0d192344e..f1e8c5806 100644 --- a/niucloud/app/service/api/pay/PayService.php +++ b/niucloud/app/service/api/pay/PayService.php @@ -12,9 +12,15 @@ namespace app\service\api\pay; use app\dict\common\ChannelDict; +use app\dict\pay\PayDict; +use app\dict\pay\PaySceneDict; +use app\model\member\Member; +use app\model\pay\Pay; +use app\model\sys\Poster; use app\service\core\member\CoreMemberService; use app\service\core\pay\CorePayService; use core\base\BaseApiService; +use core\exception\ApiException; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; @@ -57,7 +63,7 @@ class PayService extends BaseApiService break; } - return $this->core_pay_service->pay($trade_type, $trade_id, $type, $this->channel, $openid, $return_url, $quit_url, $buyer_id, $voucher); + return $this->core_pay_service->pay($trade_type, $trade_id, $type, $this->channel, $openid, $return_url, $quit_url, $buyer_id, $voucher, $this->member_id); } /** @@ -90,8 +96,45 @@ class PayService extends BaseApiService return $this->core_pay_service->getInfoByOutTradeNo($out_trade_no, $this->channel); } - public function getInfoByTrade(string $trade_type, int $trade_id){ - return $this->core_pay_service->getInfoByTrade($trade_type, $trade_id, $this->channel); + public function getInfoByTrade(string $trade_type, int $trade_id, array $data){ + return $this->core_pay_service->getInfoByTrade($trade_type, $trade_id, $this->channel, $data['scene']); + } + + /** + * 获取找朋友帮忙付支付信息 + * @param string $trade_type + * @param int $trade_id + * @return array + */ + public function getFriendspayInfoByTrade($trade_type, $trade_id){ + $from_pay_info = ( new Pay() )->field('id')->where([ [ 'trade_type', '=', $trade_type ], [ 'trade_id', '=', $trade_id ] ])->findOrEmpty()->toArray();//查询发起交易所属的站点id + if (empty($from_pay_info)) throw new ApiException('TRADE_NOT_EXIST'); + $pay_info = $this->core_pay_service->getInfoByTrade($trade_type, $trade_id, $this->channel, PaySceneDict::FRIENDSPAY); + if (!empty($pay_info)) { + //todo 查询订单交易信息,其它插件可实现该钩子 + $trade_info = array_values(array_filter(event('PayTradeInfo',[ 'trade_type' => $trade_type, 'trade_id' => $trade_id ])))[0] ?? []; + $pay_info['trade_info'] = $trade_info; + if ($pay_info['from_main_id'] != $this->member_id) { + $pay_info['is_self'] = false; + } else { + $pay_info['is_self'] = true; + } + //海报 + $poster = ( new Poster() )->field('id')->where([ + [ 'type', '=', 'friendspay' ], + [ 'status', '=', 1 ], + [ 'is_default', '=', 1 ] + ])->findOrEmpty()->toArray(); + if (!empty($poster)) { + $pay_info['poster_id'] = $poster['id']; + } + //发起帮付会员信息 + $member = ( new Member() )->field('member_id,nickname,headimg')->where([ + [ 'member_id', '=', $pay_info['from_main_id'] ] + ])->findOrEmpty()->toArray(); + $pay_info['member'] = $member; + } + return $pay_info; } /** diff --git a/niucloud/app/service/core/member/CoreMemberAddressService.php b/niucloud/app/service/core/member/CoreMemberAddressService.php index 428068ae5..92e82c118 100644 --- a/niucloud/app/service/core/member/CoreMemberAddressService.php +++ b/niucloud/app/service/core/member/CoreMemberAddressService.php @@ -13,6 +13,7 @@ namespace app\service\core\member; use app\model\member\MemberAddress; use core\base\BaseCoreService; +use core\exception\CommonException; /** * 会员标签服务层 @@ -28,6 +29,66 @@ class CoreMemberAddressService extends BaseCoreService $this->model = new MemberAddress(); } + /** + * 获取会员收货地址列表 + * @param array $where + * @return array + */ + public function getList(array $where = []) + { + if (empty($where['member_id'])) throw new CommonException('MEMBER_NOT_EXIST'); + $field = 'id, member_id, name, mobile, province_id, city_id, district_id, address, address_name, full_address, lng, lat, is_default'; + $order = 'is_default desc, id desc'; + + $list = $this->model->where([ ['member_id', '=', $where['member_id'] ] ])->field($field)->order($order)->select()->toArray(); + return $list; + } + + /** + * 获取会员收货地址信息 + * @param int $id + * @param array $data + * @return array + */ + public function getInfo(int $id, array $data) + { + if (empty($data['member_id'])) throw new CommonException('MEMBER_NOT_EXIST'); + $field = 'id,member_id,name,mobile,province_id,city_id,district_id,address,address_name,full_address,lng,lat,is_default'; + + $info = $this->model->field($field)->where([ ['id', '=', $id], ['member_id', '=', $data['member_id'] ] ])->findOrEmpty()->toArray(); + return $info; + } + + /** + * 添加会员收货地址 + * @param array $data + * @return mixed + */ + public function add(array $data) + { + if (empty($data['member_id'])) throw new CommonException('MEMBER_NOT_EXIST'); + if ($data['is_default']) { + $this->model->where([ ['member_id', '=', $data['member_id'] ] ])->update(['is_default' => 0]); + } + $res = $this->model->create($data); + return $res->id; + } + + /** + * 会员收货地址编辑 + * @param int $id + * @param array $data + * @return bool + */ + public function edit(int $id, array $data) + { + if (empty($data['member_id'])) throw new CommonException('MEMBER_NOT_EXIST'); + if ($data['is_default']) { + $this->model->where([ ['member_id', '=', $data['member_id'] ] ])->update(['is_default' => 0]); + } + $this->model->where([ ['id', '=', $id], ['member_id', '=', $data['member_id'] ] ])->update($data); + return true; + } /** * 获取会员默认地址 diff --git a/niucloud/app/service/core/pay/CorePayChannelService.php b/niucloud/app/service/core/pay/CorePayChannelService.php index c0f562e74..52d041823 100644 --- a/niucloud/app/service/core/pay/CorePayChannelService.php +++ b/niucloud/app/service/core/pay/CorePayChannelService.php @@ -40,7 +40,8 @@ class CorePayChannelService extends BaseCoreService * @param array $where * @return PayChannel|array|mixed|Model */ - public function find(array $where){ + public function find(array $where) + { return $this->model->where($where)->findOrEmpty(); } @@ -53,21 +54,35 @@ class CorePayChannelService extends BaseCoreService * @throws DbException * @throws ModelNotFoundException */ - public function getAllowPayTypeByChannel(string $channel, string $trade_type = ''){ - $channel_pay_list = $this->model->where([['channel', '=', $channel], ['status', '=', 1]])->field('type,config')->order('sort asc')->select()->toArray(); + public function getAllowPayTypeByChannel(string $channel, string $trade_type = '') + { + $channel_pay_list = $this->model->where([ [ 'channel', '=', $channel ], [ 'status', '=', 1 ] ])->field('type,config')->order('sort asc')->select()->toArray(); - if(!empty($channel_pay_list)){ + if (!empty($channel_pay_list)) { $temp_channel_pay_list = array_column($channel_pay_list, 'type'); - $pay_type_list = PayDict::getPayType($temp_channel_pay_list); + $pay_type_arr = PayDict::getPayType($temp_channel_pay_list); + foreach ($temp_channel_pay_list as $key) { + if (isset($pay_type_arr[$key])) { + $pay_type_list[$key] = $pay_type_arr[$key]; + } + } } - //充值订单不支持余额支付 - if(!empty($pay_type_list) && $trade_type == 'recharge'){ - unset($pay_type_list[PayDict::BALANCEPAY]); + //充值订单不支持余额支付和找朋友帮忙付 + if (!empty($pay_type_list) && $trade_type == 'recharge') { + unset($pay_type_list[ PayDict::BALANCEPAY ], $pay_type_list[ PayDict::FRIENDSPAY ]); } // 线下支付做处理 - if (!empty($pay_type_list) && isset($pay_type_list[PayDict::OFFLINEPAY])) { + if (!empty($pay_type_list) && isset($pay_type_list[ PayDict::OFFLINEPAY ])) { $temp_channel_pay_list = array_column($channel_pay_list, null, 'type'); - $pay_type_list[PayDict::OFFLINEPAY]['config'] = $temp_channel_pay_list[PayDict::OFFLINEPAY]['config']; + $pay_type_list[ PayDict::OFFLINEPAY ][ 'config' ] = $temp_channel_pay_list[ PayDict::OFFLINEPAY ][ 'config' ]; + } + // 找朋友帮忙付做处理 + if (!empty($pay_type_list) && isset($pay_type_list[ PayDict::FRIENDSPAY ])) { + $temp_channel_pay_list = array_column($channel_pay_list, null, 'type'); + $pay_type_list[ PayDict::FRIENDSPAY ][ 'config' ] = $temp_channel_pay_list[ PayDict::FRIENDSPAY ][ 'config' ]; + if (!empty($temp_channel_pay_list[ PayDict::FRIENDSPAY ][ 'config' ])) { + $pay_type_list[ PayDict::FRIENDSPAY ][ 'name' ] = $temp_channel_pay_list[ PayDict::FRIENDSPAY ][ 'config' ][ 'pay_type_name' ]; + } } return $pay_type_list ?? []; @@ -79,10 +94,11 @@ class CorePayChannelService extends BaseCoreService * @param string $type * @return array|mixed */ - public function getConfigByChannelAndType(string $channel, string $type){ - $pay_channel = $this->model->where([ ['channel', '=', $channel], ['type', '=', $type]])->field('config')->findOrEmpty(); - if(!$pay_channel->isEmpty()){ - if($type == PayDict::WECHATPAY){ + public function getConfigByChannelAndType(string $channel, string $type) + { + $pay_channel = $this->model->where([ [ 'channel', '=', $channel ], [ 'type', '=', $type ] ])->field('config')->findOrEmpty(); + if (!$pay_channel->isEmpty()) { + if ($type == PayDict::WECHATPAY) { $pay_channel->config = array_merge($pay_channel->config, $this->getWechatPayFullConfig()); } return $pay_channel->config; @@ -90,19 +106,19 @@ class CorePayChannelService extends BaseCoreService return []; } - /** * 获取完整的微信支付配置(根据场景) * @return array */ - public function getWechatPayFullConfig(){ + public function getWechatPayFullConfig() + { //TODO 先判断是否是开放平台授权,然后再决定使用什么appid //查询公众号配置 $core_wechat_config_service = new CoreWechatConfigService(); - $mp_app_id = $core_wechat_config_service->getWechatConfig()['app_id'];//公众号appid + $mp_app_id = $core_wechat_config_service->getWechatConfig()[ 'app_id' ];//公众号appid //查询公众号配置 $core_weapp_config_service = new CoreWeappConfigService(); - $mini_app_id = $core_weapp_config_service->getWeappConfig()['app_id'];//小程序appid + $mini_app_id = $core_weapp_config_service->getWeappConfig()[ 'app_id' ];//小程序appid //todo 查询微信小程序 appid . 应用appid..... return [ 'mp_app_id' => $mp_app_id, diff --git a/niucloud/app/service/core/pay/CorePayEventService.php b/niucloud/app/service/core/pay/CorePayEventService.php index ff290bc19..289d8e743 100644 --- a/niucloud/app/service/core/pay/CorePayEventService.php +++ b/niucloud/app/service/core/pay/CorePayEventService.php @@ -23,7 +23,6 @@ use think\Response; use Yansongda\Pay\Exception\ContainerException; use Yansongda\Pay\Exception\InvalidParamsException; use Yansongda\Pay\Exception\ServiceNotFoundException; -use Yansongda\Supports\Collection; /** * 支付服务层 @@ -42,7 +41,6 @@ class CorePayEventService extends BaseCoreService parent::__construct(); } - /** * 支付引擎外置触点初始化 * @param string $channel @@ -70,7 +68,6 @@ class CorePayEventService extends BaseCoreService return new PayLoader($this->type, $this->config); } - /** * 去支付 * @param string $out_trade_no diff --git a/niucloud/app/service/core/pay/CorePayService.php b/niucloud/app/service/core/pay/CorePayService.php index e738b67dc..bf63bd359 100644 --- a/niucloud/app/service/core/pay/CorePayService.php +++ b/niucloud/app/service/core/pay/CorePayService.php @@ -13,6 +13,7 @@ namespace app\service\core\pay; use app\dict\pay\OnlinePayDict; use app\dict\pay\PayDict; +use app\dict\pay\PaySceneDict; use app\job\pay\PayReturnTo; use app\model\pay\Pay; use core\base\BaseCoreService; @@ -21,7 +22,6 @@ use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; use think\facade\Db; -use think\facade\Log; use think\Model; use Throwable; @@ -61,6 +61,7 @@ class CorePayService extends BaseCoreService 'body' => $body, 'out_trade_no' => $out_trade_no, 'main_id' => $main_id, + 'from_main_id' => $main_id, 'main_type' => $main_type ); $this->model->create($data); @@ -119,6 +120,30 @@ class CorePayService extends BaseCoreService return $pay; } + /** + * 通过业务类型和id查询支付状态 + * @param string $trade_type + * @param int $trade_id + * @return bool + */ + public function getPayStatusByTrade(string $trade_type, int $trade_id) + { + $where = array( + [ 'trade_type', '=', $trade_type ], + [ 'trade_id', '=', $trade_id ], + ); + $pay_info = $this->model->field('status')->where($where)->findOrEmpty(); + if ($pay_info->isEmpty()) { + throw new PayException('TRADE_NOT_EXIST');//支付单据不存在 + } else { + if ($pay_info[ 'status' ] == PayDict::STATUS_FINISH) { + return true; + } else { + return false; + } + } + } + /** * 通过交易信息获取支付单据 * @param string $trade_type @@ -129,7 +154,7 @@ class CorePayService extends BaseCoreService * @throws DbException * @throws ModelNotFoundException */ - public function getInfoByTrade(string $trade_type, string $trade_id, string $channel) + public function getInfoByTrade(string $trade_type, string $trade_id, string $channel, string $scene = '') { $pay = $this->findPayInfoByTrade($trade_type, $trade_id); if ($pay->isEmpty()) { @@ -141,7 +166,13 @@ class CorePayService extends BaseCoreService } if (!empty($pay)) { //todo 校验场景控制支付方式 - $pay[ 'pay_type_list' ] = array_values(( new CorePayChannelService() )->getAllowPayTypeByChannel($channel, $pay[ 'trade_type' ])); + $pay_type_list = ( new CorePayChannelService() )->getAllowPayTypeByChannel($channel, $pay[ 'trade_type' ]); + //找朋友帮忙付时不支持找朋友帮忙付 + if(!empty($pay_type_list) && !empty($pay_type_list[PayDict::FRIENDSPAY]) && $scene == PaySceneDict::FRIENDSPAY){ + $pay[ 'config' ] = $pay_type_list[PayDict::FRIENDSPAY]['config']; + unset($pay_type_list[PayDict::FRIENDSPAY]); + } + $pay[ 'pay_type_list' ] = array_values($pay_type_list); } return $pay; } @@ -176,7 +207,7 @@ class CorePayService extends BaseCoreService * @throws DbException * @throws ModelNotFoundException */ - public function pay($trade_type, $trade_id, $type, $channel, string $openid, string $return_url = '', string $quit_url = '', string $buyer_id = '', string $voucher = '') + public function pay($trade_type, $trade_id, $type, $channel, string $openid, string $return_url = '', string $quit_url = '', string $buyer_id = '', string $voucher = '', $member_id = 0) { //检测并创建支付单据 $pay = $this->checkOrCreate($trade_type, $trade_id); @@ -185,10 +216,19 @@ class CorePayService extends BaseCoreService $body = $pay[ 'body' ]; $trade_type = $pay[ 'trade_type' ]; if (!in_array($type, array_column(( new CorePayChannelService() )->getAllowPayTypeByChannel($channel, $trade_type), 'key'))) throw new PayException('PAYMENT_METHOD_NOT_SCENE');//场景不支持 + if ($member_id != 0) { + //更新付款人id + $pay_info = $this->findPayInfoByTrade($trade_type, $trade_id); + $pay_info->save([ + 'main_id' => $member_id + ]); + } $pay_result = $this->pay_event->init($channel, $type)->pay($out_trade_no, $money, $body, $return_url, $quit_url, $buyer_id, $openid ?? '', $voucher); //todo 特殊支付方式会直接返回支付状态,状态如果为已支付会直接支付 if (!empty($pay_result[ 'status' ]) && $pay_result[ 'status' ] == PayDict::STATUS_FINISH) { - $pay->save([ 'channel' => $channel ]); + $pay->save([ + 'channel' => $channel + ]); $this->paySuccess([ 'status' => PayDict::STATUS_FINISH, 'type' => $type, @@ -488,6 +528,7 @@ class CorePayService extends BaseCoreService $type = $params[ 'type' ]; $trade_type = $pay->trade_type; $trade_id = $pay->trade_id; + $main_id = $pay->main_id; $data = array( 'pay_time' => time(), 'status' => PayDict::STATUS_FINISH, @@ -503,7 +544,7 @@ class CorePayService extends BaseCoreService Db::startTrans(); try { $pay->allowField($allow_field)->save($data); - $result = event('PaySuccess', [ 'out_trade_no' => $out_trade_no, 'trade_type' => $trade_type, 'trade_id' => $trade_id ]); + $result = event('PaySuccess', [ 'out_trade_no' => $out_trade_no, 'trade_type' => $trade_type, 'trade_id' => $trade_id, 'main_id' => $main_id ]); // if (!check_event_result($result)) { // Db::rollback(); // return false; diff --git a/niucloud/app/service/core/pay/CoreRefundService.php b/niucloud/app/service/core/pay/CoreRefundService.php index 717228e78..7bd12a937 100644 --- a/niucloud/app/service/core/pay/CoreRefundService.php +++ b/niucloud/app/service/core/pay/CoreRefundService.php @@ -21,7 +21,7 @@ use Throwable; /** * 退款服务层 - * Class CorePayService + * Class CoreRefundService * @package app\service\core\pay */ class CoreRefundService extends BaseCoreService diff --git a/niucloud/app/upgrade/v144/Upgrade.php b/niucloud/app/upgrade/v144/Upgrade.php new file mode 100644 index 000000000..423fbc571 --- /dev/null +++ b/niucloud/app/upgrade/v144/Upgrade.php @@ -0,0 +1,42 @@ +handleDiyData(); + } + + /** + * 处理自定义数据 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + private function handleDiyData() + { + + $poster_model = new Poster(); + $poster = new CorePosterService(); + $template = $poster->getTemplateList('', 'friendspay')[ 0 ]; + + $poster_model->where([ [ 'type', '=', 'friendspay' ] ])->delete(); + // 创建默认找朋友帮忙付海报 + $poster->add('', [ + 'name' => $template[ 'name' ], + 'type' => $template[ 'type' ], + 'value' => $template[ 'data' ], + 'status' => 1, + 'is_default' => 1 + ]); + } + +} diff --git a/niucloud/app/upgrade/v144/upgrade.sql b/niucloud/app/upgrade/v144/upgrade.sql new file mode 100644 index 000000000..74beb4648 --- /dev/null +++ b/niucloud/app/upgrade/v144/upgrade.sql @@ -0,0 +1,4 @@ + +ALTER TABLE `pay` ADD COLUMN `from_main_id` INT(11) NOT NULL DEFAULT 0 COMMENT '发起支付会员id'; + +ALTER TABLE `pay` MODIFY `from_main_id` INT(11) NOT NULL DEFAULT 0 COMMENT '发起支付会员id' AFTER `main_id`; diff --git a/niucloud/config/version.php b/niucloud/config/version.php index c03c5082f..7d5129234 100644 --- a/niucloud/config/version.php +++ b/niucloud/config/version.php @@ -1,7 +1,6 @@ '1.4.3', - 'code' => '202412120001' + 'version' => '1.4.4', + 'code' => '202501030001' ]; - \ No newline at end of file diff --git a/niucloud/core/dict/RechargeGift.php b/niucloud/core/dict/RechargeGift.php new file mode 100644 index 000000000..ed9ca7942 --- /dev/null +++ b/niucloud/core/dict/RechargeGift.php @@ -0,0 +1,43 @@ +getLocalAddons(); + foreach ($addons as $v) { + $addon_change_type_file = $this->getAddonDictPath($v) . "recharge" . DIRECTORY_SEPARATOR . "package_gift.php"; + if (is_file($addon_change_type_file)) { + $account_change_type_files[] = $addon_change_type_file; + } + } + $account_change_type_datas = $this->loadFiles($account_change_type_files); + $account_change_type_array = []; + foreach ($account_change_type_datas as $account_change_type_data) { + $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); + } + foreach ($account_change_type_array as $key => &$value) { + $value[ 'key' ] = $key; + } + usort($account_change_type_array, function($list_one, $list_two) { + return $list_one[ 'sort' ] <=> $list_two[ 'sort' ]; + }); + return $account_change_type_array; + + } +} diff --git a/niucloud/core/pay/Wechatpay.php b/niucloud/core/pay/Wechatpay.php index d7d397322..6ccd1bc90 100644 --- a/niucloud/core/pay/Wechatpay.php +++ b/niucloud/core/pay/Wechatpay.php @@ -5,7 +5,6 @@ namespace core\pay; use app\dict\pay\OnlinePayDict; use app\dict\pay\RefundDict; use app\dict\pay\TransferDict; -use core\exception\CommonException; use core\exception\PayException; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; diff --git a/niucloud/core/upload/Local.php b/niucloud/core/upload/Local.php index 417119416..872baa309 100644 --- a/niucloud/core/upload/Local.php +++ b/niucloud/core/upload/Local.php @@ -53,7 +53,11 @@ class Local extends BaseUpload { try { mkdirs_or_notexist(dirname($key), 0777); - $content = @file_get_contents($url); + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $content = curl_exec($ch); + curl_close($ch); + // $content = @file_get_contents($url);//file_get_contents下载网络图片慢,更换为curl下载 if (!empty($content)) { file_put_contents($key, $content);