123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- <?php
- namespace app\data\service;
- use app\data\model\BaseUserPayment;
- use app\data\model\DataUser;
- use app\data\model\DataUserPayment;
- use app\data\model\DataUserVipOrder;
- use app\data\model\ShopGoods;
- use app\data\model\ShopOrder;
- use app\data\model\ShopOrderItem;
- use app\data\model\ShopOrderPay;
- use app\data\model\ShopGoodsItem;
- use app\data\service\payment\AlipayPaymentService;
- use app\data\service\payment\BalancePaymentService;
- use app\data\service\payment\EmptyPaymentService;
- use app\data\service\payment\JoinpayPaymentService;
- use app\data\service\payment\VoucherPaymentService;
- use app\data\service\payment\WechatPaymentService;
- use think\admin\Exception;
- use think\admin\Library;
- use think\App;
- use app\data\model\SystemUserMessage;
- /**
- * 支付基础服务
- * Class PaymentService
- * @package app\data\service
- */
- abstract class PaymentService
- {
- // 用户余额支付
- const PAYMENT_EMPTY = 'empty';
- const PAYMENT_BALANCE = 'balance';
- const PAYMENT_VOUCHER = 'voucher';
- // 汇聚支付参数
- const PAYMENT_JOINPAY_GZH = 'joinpay_gzh';
- const PAYMENT_JOINPAY_XCX = 'joinpay_xcx';
- // 微信商户支付
- const PAYMENT_WECHAT_APP = 'wechat_app';
- const PAYMENT_WECHAT_GZH = 'wechat_gzh';
- const PAYMENT_WECHAT_XCX = 'wechat_xcx';
- const PAYMENT_WECHAT_WAP = 'wechat_wap';
- const PAYMENT_WECHAT_QRC = 'wechat_qrc';
- // 支付宝支付参数
- const PAYMENT_ALIAPY_APP = 'alipay_app';
- const PAYMENT_ALIPAY_WAP = 'alipay_wap';
- const PAYMENT_ALIPAY_WEB = 'alipay_web';
- // 支付通道配置,不需要的可以注释
- const TYPES = [
- // 空支付,金额为零时自动完成支付
- self::PAYMENT_EMPTY => [
- 'type' => 'EMPTY',
- 'name' => '订单无需支付',
- 'bind' => [],
- ],
- // 余额支付,使用账号余额完成支付
- self::PAYMENT_BALANCE => [
- 'type' => 'BALANCE',
- 'name' => '账号余额支付',
- 'bind' => [
- UserAdminService::API_TYPE_WAP, UserAdminService::API_TYPE_WEB,
- UserAdminService::API_TYPE_WXAPP, UserAdminService::API_TYPE_WECHAT,
- UserAdminService::API_TYPE_IOSAPP, UserAdminService::API_TYPE_ANDROID,
- ],
- ],
- // 凭证支付,上传凭证后台审核支付
- self::PAYMENT_VOUCHER => [
- 'type' => 'VOUCHER',
- 'name' => '单据凭证支付',
- 'bind' => [
- UserAdminService::API_TYPE_WAP, UserAdminService::API_TYPE_WEB,
- UserAdminService::API_TYPE_WXAPP, UserAdminService::API_TYPE_WECHAT,
- UserAdminService::API_TYPE_IOSAPP, UserAdminService::API_TYPE_ANDROID,
- ],
- ],
- // 微信支付配置(不需要的直接注释)
- self::PAYMENT_WECHAT_WAP => [
- 'type' => 'MWEB',
- 'name' => '微信WAP支付',
- 'bind' => [UserAdminService::API_TYPE_WAP],
- ],
- self::PAYMENT_WECHAT_APP => [
- 'type' => 'APP',
- 'name' => '微信APP支付',
- 'bind' => [UserAdminService::API_TYPE_IOSAPP, UserAdminService::API_TYPE_ANDROID],
- ],
- self::PAYMENT_WECHAT_XCX => [
- 'type' => 'JSAPI',
- 'name' => '微信小程序支付',
- 'bind' => [UserAdminService::API_TYPE_WXAPP],
- ],
- self::PAYMENT_WECHAT_GZH => [
- 'type' => 'JSAPI',
- 'name' => '微信公众号支付',
- 'bind' => [UserAdminService::API_TYPE_WECHAT],
- ],
- self::PAYMENT_WECHAT_QRC => [
- 'type' => 'NATIVE',
- 'name' => '微信二维码支付',
- 'bind' => [UserAdminService::API_TYPE_WEB],
- ],
- // 支付宝支持配置(不需要的直接注释)
- self::PAYMENT_ALIPAY_WAP => [
- 'type' => '',
- 'name' => '支付宝WAP支付',
- 'bind' => [UserAdminService::API_TYPE_WAP],
- ],
- self::PAYMENT_ALIPAY_WEB => [
- 'type' => '',
- 'name' => '支付宝WEB支付',
- 'bind' => [UserAdminService::API_TYPE_WEB],
- ],
- self::PAYMENT_ALIAPY_APP => [
- 'type' => 'alipay_app',
- 'name' => '支付宝APP支付',
- 'bind' => [UserAdminService::API_TYPE_ANDROID, UserAdminService::API_TYPE_IOSAPP],
- ],
- // 汇聚支持配置(不需要的直接注释)
- self::PAYMENT_JOINPAY_XCX => [
- 'type' => 'WEIXIN_XCX',
- 'name' => '汇聚小程序支付',
- 'bind' => [UserAdminService::API_TYPE_WXAPP],
- ],
- self::PAYMENT_JOINPAY_GZH => [
- 'type' => 'WEIXIN_GZH',
- 'name' => '汇聚公众号支付',
- 'bind' => [UserAdminService::API_TYPE_WECHAT],
- ],
- ];
- /**
- * 支付服务对象
- * @var array
- */
- protected static $driver = [];
- /**
- * 当前应用
- * @var App
- */
- protected $app;
- /**
- * 支付参数编号
- * @var string
- */
- protected $code;
- /**
- * 默认支付类型
- * @var string
- */
- protected $type;
- /**
- * 当前支付参数
- * @var array
- */
- protected $params;
- /**
- * PaymentService constructor.
- * @param App $app 当前应用对象
- * @param string $code 支付参数编号
- * @param string $type 支付类型代码
- * @param array $params 支付参数配置
- */
- public function __construct(App $app, string $code, string $type, array $params)
- {
- [$this->app, $this->code, $this->type, $this->params] = [$app, $code, $type, $params];
- if (method_exists($this, 'initialize')) $this->initialize();
- }
- /**
- * 根据配置实例支付服务
- * @param string $code 支付配置编号
- * @return PaymentService
- * @throws \think\admin\Exception
- */
- public static function instance(string $code): PaymentService
- {
- if ($code === 'empty') {
- $vars = ['code' => 'empty', 'type' => 'empty', 'params' => []];
- return static::$driver[$code] = Library::$sapp->make(EmptyPaymentService::class, $vars);
- }
- [, $type, $params] = self::config($code);
- if (isset(static::$driver[$code])) return static::$driver[$code];
- $vars = ['code' => $code, 'type' => $type, 'params' => $params];
- // 实例化具体支付参数类型
- if (stripos($type, 'balance') === 0) {
- return static::$driver[$code] = Library::$sapp->make(BalancePaymentService::class, $vars);
- } elseif (stripos($type, 'voucher') === 0) {
- return static::$driver[$code] = Library::$sapp->make(VoucherPaymentService::class, $vars);
- } elseif (stripos($type, 'alipay_') === 0) {
- return static::$driver[$code] = Library::$sapp->make(AlipayPaymentService::class, $vars);
- } elseif (stripos($type, 'wechat_') === 0) {
- return static::$driver[$code] = Library::$sapp->make(WechatPaymentService::class, $vars);
- } elseif (stripos($type, 'joinpay_') === 0) {
- return static::$driver[$code] = Library::$sapp->make(JoinpayPaymentService::class, $vars);
- } else {
- throw new Exception(sprintf('支付驱动[%s]未定义', $type));
- }
- }
- /**
- * 获取支付配置参数
- * @param string $code
- * @param array $payment
- * @return array [code, type, params]
- * @throws Exception
- */
- public static function config(string $code, array $payment = []): array
- {
- try {
- if (empty($payment)) {
- $map = ['code' => $code, 'status' => 1, 'deleted' => 0];
- $payment = BaseUserPayment::mk()->where($map)->find();
- }
- if (empty($payment)) {
- throw new Exception("支付参数[#{$code}]禁用关闭");
- }
- $params = @json_decode($payment['content'], true);
- if (empty($params)) {
- throw new Exception("支付参数[#{$code}]配置无效");
- }
- if (empty(static::TYPES[$payment['type']])) {
- throw new Exception("支付参数[@{$payment['type']}]匹配失败");
- }
- return [$payment['code'], $payment['type'], $params];
- } catch (\Exception $exception) {
- throw new Exception($exception->getMessage(), $exception->getCode());
- }
- }
- /**
- * 获取支付支付名称
- * @param string $type
- * @return string
- */
- public static function name(string $type): string
- {
- return static::TYPES[$type]['name'] ?? $type;
- }
- /**
- * 获取支付类型
- * @param array $types 默认返回支付
- * @return array
- */
- public static function getTypeAll(array $types = []): array
- {
- $binds = array_keys(UserAdminService::TYPES);
- foreach (static::TYPES as $k => $v) if (isset($v['bind'])) {
- if (array_intersect($v['bind'], $binds)) $types[$k] = $v;
- }
- return $types;
- }
- /**
- * 筛选可用的支付类型
- * @param string $api 指定接口类型
- * @param array $types 默认返回支付
- * @return array
- */
- public static function getTypeApi(string $api = '', array $types = []): array
- {
- foreach (self::TYPES as $type => $attr) {
- if (in_array($api, $attr['bind'])) $types[] = $type;
- }
- return array_unique($types);
- }
- /**
- * 订单主动查询
- * @param string $orderNo
- * @return array
- */
- abstract public function query(string $orderNo): array;
- /**
- * 支付通知处理
- * @return string
- */
- abstract public function opvip(): string;
- /**
- * 支付通知处理
- * @return string
- */
- abstract public function payorder(): string;
- /**
- * 创建支付订单
- * @param string $openid 用户OPENID
- * @param string $orderNo 交易订单单号
- * @param string $payAmount 交易订单金额(元)
- * @param string $payTitle 交易订单名称
- * @param string $payRemark 交易订单描述
- * @param string $payReturn 支付回跳地址
- * @param string $payImage 支付凭证图片
- * @return array
- */
- abstract public function create(string $openid, string $orderNo, string $payAmount, string $payTitle, string $payRemark, string $payReturn = '', string $payImage = '',string $notify_url = '',array $parm = []): array;
- /**
- * 创建支付行为
- * @param string $orderNo 商户订单单号
- * @param string $payTitle 商户订单标题
- * @param string $payAmount 需要支付金额
- */
- protected function createPaymentAction(string $orderNo, string $payTitle, string $payAmount)
- {
- DataUserPayment::mk()->insert([
- 'payment_code' => $this->code,
- 'payment_type' => $this->type,
- 'order_no' => $orderNo,
- 'order_name' => $payTitle,
- 'order_amount' => $payAmount,
- ]);
- }
- /**
- * 更新开通vip会员订单
- * @return boolean
- */
- protected function updateOpvipAction(array $notify): bool
- {
- $orderNo = $notify['out_trade_no'];
- $order = DataUserVipOrder::mk()->where('order_no',$orderNo)->findOrEmpty();
- if ($order->isEmpty()) return false;
- if ($order['status']) return false;
- if ($order->pay_type=='balance'){
- //余额支付
- $resu = userMoneyChange($order->yue_price,1,$order->uuid,'开通vip',0,$order->id);
- if (!$resu) return false;
- }
- $user = DataUser::mk()->where('id',$order->uuid)->findOrEmpty();
- DataUser::mk()->where('id',$order->uuid)->update(
- [
- 'is_vip'=>1,
- 'vip_name'=>'船白知会员',
- 'vip_order'=>$order->id,
- 'vip_datetime'=> $user->is_vip ? date('Y-m-d H:i:s',strtotime($user->vip_datetime)+(365*24*60*60)) : date('Y-m-d H:i:s',time()+(365*24*60*60))
- ]
- );
- // 更新支付记录
- $order->status = 1;
- $order->pay_at = date('Y-m-d H:i:s');
- $order->pay_return = json_encode($notify,true);
- $order->save();
- // 更新记录状态
- return true;
- }
- /**
- * 更新开通vip会员订单
- * @return boolean
- */
- protected function updatePayorderAction(array $notify): bool
- {
- $orderNo = $notify['out_trade_no'];
- $order = ShopOrderPay::mk()->where('pay_no',$orderNo)->findOrEmpty();
- if ($order->isEmpty()) return false;
- $order_nos = ShopOrder::mk()->where(['payment_trade'=>$orderNo])->field('order_no')->select();
- foreach ($order_nos as &$v){
- $info = ShopOrderItem::mk()->where('order_no',$v['order_no'])->field('goods_code,goods_sku,stock_sales')->find();
- $goods = ShopGoods::mk()->where('code',$info['goods_code'])->findOrEmpty();
- $item = ShopGoodsItem::mk()->where('goods_sku',$info['goods_sku'])->findOrEmpty();
- $goods->stock_total -=$info['stock_sales'];
- $goods->stock_sales +=$info['stock_sales'];
- $item->stock_total -=$info['stock_sales'];
- $goods->save();
- $item->save();
- }
- ShopOrder::mk()->where(['payment_trade'=>$orderNo])->save(['status'=>4,'payment_datetime'=>date('Y-m-d H:i:s'),'payment_status'=>1]);
- //商家消息提醒
- $order_info = ShopOrder::mk()->where(['payment_trade'=>$orderNo])->field('order_no,admin_id')->find();
- $mes = ShopOrderItem::mk()->where('order_no',$order_info['order_no'])->find();
- $data = [
- 'type'=>2,
- 'uuid'=>$order_info['admin_id'],
- 'title'=>'买家已经付款',
- 'content'=>$mes['goods_name'],
- 'image'=>$mes['goods_cover'],
- 'remark'=>'买家已经付款,请尽快发货哦~'
- ];
- $shop_order_model = new SystemUserMessage();
- $shop_order_model->systemMessageadd($data);
- // 更新支付记录
- $order->status = 2;
- $order->pay_at = date('Y-m-d H:i:s');
- $order->transaction_id = json_encode($notify,true);
- $order->save();
- // 更新记录状态
- return true;
- }
- /**
- * 订单支付更新操作
- * @param string $orderNo 订单单号
- * @param string $payTrade 交易单号
- * @param string $payAmount 支付金额
- * @param string $payRemark 支付描述
- * @param string $payImage 支付凭证
- * @return boolean
- */
- protected function updatePaymentOrder(string $orderNo, string $payTrade, string $payAmount, string $payRemark = '在线支付', string $payImage = ''): bool
- {
- $map = ['status' => 2, 'order_no' => $orderNo, 'payment_status' => 0];
- $order = ShopOrder::mk()->where($map)->findOrEmpty();
- if ($order->isEmpty()) return false;
- // 检查订单支付状态
- if ($this->type === self::PAYMENT_VOUCHER) {
- $status = 3; # 凭证支付需要审核
- } elseif (empty($order['truck_type'])) {
- $status = 6; # 虚拟订单直接完成
- } else {
- $status = 4; # 实物订单需要发货
- }
- // 更新订单支付状态
- $order['status'] = $status;
- $order['payment_code'] = $this->code;
- $order['payment_type'] = $this->type;
- $order['payment_trade'] = $payTrade;
- $order['payment_image'] = $payImage;
- $order['payment_amount'] = $payAmount;
- $order['payment_remark'] = $payRemark;
- $order['payment_status'] = 1;
- $order['payment_datetime'] = date('Y-m-d H:i:s');
- $order->save();
- // 触发订单更新事件
- if ($status >= 4) {
- $this->app->event->trigger('ShopOrderPayment', $orderNo);
- }
- return true;
- }
- }
|