<?php
/**
 *  ╔═══════════════════════════════════════════════════╗
 *  ║                                                   ║
 *  ║     ██╗  ██╗   █████╗    ██████╗                  ║
 *  ║     ██║  ██║  ██╔══██╗  ██╔═══██╗                 ║
 *  ║     ███████║  ███████║  ██║   ██║                 ║
 *  ║     ██╔══██║  ██╔══██║  ██║   ██║                 ║
 *  ║     ██║  ██║  ██║  ██║  ╚██████╔╝   SNS           ║
 *  ║                                                   ║    
 *  ║                                                   ║    
 *  ║     © 2023 HaoSNS™ All Rights Reserved            ║
 *  ║     官方网站: https://www.haosns.com                *
 *  ║     本代码由赣州乐易网络科技有限公司®提供             *
 *  ║                                                    *
 *  ║   未经授权禁止复制、传播或用于其他商业目的            *
 *  ║                                                   ║
 *  ╚═══════════════════════════════════════════════════╝
 */


namespace app\common\logic;


use app\common\enum\AfterSaleEnum;
use app\common\enum\PayEnum;
use app\common\model\Refund;
use app\common\service\pay\AliPayService;
use app\common\service\pay\BalancePayService;
use app\common\service\pay\ToutiaoPayService;
use app\common\service\pay\WeChatPayService;
use app\common\service\WeChatConfigService;

/**
 * 二手商城订单退款逻辑
 * Class OrderRefundLogic
 * @package app\common\logic
 */
class TwoRefundLogic extends BaseLogic
{

    protected static $refund;

    /**
     * @notes 发起退款
     * @param $refundWay //退款类型;(原路退,退回到余额)
     * @param $order //订单信息
     * @param $afterSaleId //售后退款id
     * @param $refundAmount //退款金额
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public static function refund($refundWay, $order, $afterSaleId, $refundAmount)
    {
        if ($refundAmount <= 0) {
            return false;
        }

        self::log($order, $afterSaleId, $refundAmount);

        //区分原路退 还是退回到余额
        if ($refundWay == AfterSaleEnum::REFUND_WAYS_BALANCE) {
            self::balancePayRefund($order, $refundAmount, $afterSaleId);
            return true;
        }

        switch ($order['pay_way']) {
            //余额退款
            case PayEnum::BALANCE_PAY:
                self::balancePayRefund($order, $refundAmount,$afterSaleId);
                break;
            //微信退款
            case PayEnum::WECHAT_PAY:
                self::wechatPayRefund($order, $refundAmount);
                break;
            //支付宝退款
            case PayEnum::ALI_PAY:
                self::aliPayRefund($order, $refundAmount);
                break;
        }

        return true;
    }



    /**
     * @notes 余额退款
     * @param $order
     * @param $refundAmount
     */
    public static function balancePayRefund($order, $refundAmount,$afterSaleId)
    {
        (new BalancePayService())->refund($order, $refundAmount,$afterSaleId,'two');
    }



    /**
     * @notes 微信退款
     * @param $refundWay
     * @param $order
     * @param $refundAmount
     * @return bool|void
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public static function wechatPayRefund($order, $refundAmount)
    {
        //原来退回到微信的情况
        $wechatConfig = WeChatConfigService::getWechatConfigByTerminal($order['order_terminal']);

        if (!isset($wechatConfig['cert_path']) || !isset($wechatConfig['key_path'])) {
            throw new \Exception('请联系管理员设置微信证书!');
        }

        if (!file_exists($wechatConfig['cert_path']) || !file_exists($wechatConfig['key_path'])) {
            throw new \Exception('微信证书不存在,请联系管理员!');
        }

        //发起退款
        $result = (new WeChatPayService($order['order_terminal']))->refund([
            'transaction_id' => $order['transaction_id'],
            'refund_sn' => self::$refund['sn'],
            'total_fee' => intval(strval($order['order_amount'] * 100)),//订单金额,单位为分
            'refund_fee' => intval(strval($refundAmount * 100)),//退款金额
        ]);

        if (isset($result['return_code']) && $result['return_code'] == 'FAIL') {
            throw new \Exception($result['return_msg']);
        }

        if (isset($result['err_code_des'])) {
            throw new \Exception($result['err_code_des']);
        }

        //更新退款日志记录
        Refund::update([
            'wechat_refund_id' => $result['refund_id'] ?? 0,
            'refund_status' => (isset($result['result_code']) && $result['result_code'] == 'SUCCESS') ? 1 : 2,
            'refund_msg' => json_encode($result, JSON_UNESCAPED_UNICODE),
        ], ['id' => self::$refund['id']]);

        if ($result['return_code'] == 'FAIL' || $result['result_code'] == 'FAIL') {
            throw new \Exception('微信支付退款失败');
        }

        return true;
    }


    /**
     * @notes 支付宝退款
     * @param $order
     * @param $refundAmount
     * @return bool
     * @throws \Exception
     */
    public static function aliPayRefund($order, $refundAmount)
    {
        //原路退回到支付宝的情况
        $result = (new AliPayService())->refund($order['sn'], $refundAmount, self::$refund['sn']);
        $result = (array)$result;

        //更新退款日志记录
        Refund::update([
            'refund_status' => (isset($result['result_code']) && $result['result_code'] == 'SUCCESS') ? 1 : 2,
            'refund_msg' => json_encode($result['httpBody'], JSON_UNESCAPED_UNICODE),
        ], ['id' => self::$refund['id']]);

        if ($result['code'] != '10000' || $result['msg'] != 'Success' || $result['fundChange'] != 'Y') {
            throw new \Exception('支付宝退款失败');
        }

        return true;
    }


    /**
     * @notes 退款日志
     * @param $order
     * @param $afterSaleId
     * @param $refundAmount
     */
    public static function log($order, $afterSaleId, $refundAmount)
    {
        $result = Refund::create([
            'order_id' => $order['id'],
            'after_sale_id' => $afterSaleId,
            'user_id' => $order['user_id'],
            'sn' => generate_sn(new Refund(), 'sn'),
            'order_amount' => $order['order_amount'],
            'refund_amount' => $refundAmount,
        ]);

        self::$refund = $result;
    }

}