<?php
namespace App\Helper\UniPlatform;

/**
 * Class ByteDance
 *
 * @package App\Helper
 * @property-read  string $appId
 * @property-read  string $slat
 * @property-read  string $secret
 * @property-read  string $token
 * @property-read  string $accessTokenDir
 * @property-read  string $accessTokenFile
 * @property-read  string $accessToken
 * @property-read  string $noticeUrl
 * @property-read  string $validTimestamp
 * @property-read  BaseAPI $API
 */
abstract class BaseUniPlatform
{
    protected $appId = null;
    protected $mchId = null;
    protected $mchKey = null;
    protected $secret = null;
    protected $slat = null;
    protected $token = null;


    protected $accessTokenDir = null;
    protected $accessTokenFile = null;
    protected $accessToken = null;
    protected $noticeUrl = null;
    //订单过期时间(秒);
    protected $validTimestamp = 24 * 60 * 60;

    protected $API;

    /**
     * @param array $config
     * @return $this
     */
    public function factory($config = [])
    {
        $this->appId = $config['app_id'];
        $this->secret = $config['app_secret'];
        $this->slat = isset($config['slat']) ? $config['slat'] : null;
        $this->token = isset($config['token']) ?  $config['token'] : null;
        $this->mchId = isset($config['mch_id']) ?  $config['mch_id'] : null;
        $this->mchKey = isset($config['mch_key']) ?  $config['mch_key'] : null;

        $this->setAccessFileDir();
        $this->setAccessFilePath();
        $this->setNoticeUrl();
        $this->accessToken = $this->checkAccessToken();

        return $this;
    }


    /**
     * @param string $sessionKey
     * @param string $iv
     * @param string $encrypted
     * @return array
     * @throws \Exception
     */
    public function decryptData(string $sessionKey, string $iv, string $encrypted): array
    {
        $decrypted =  openssl_decrypt(
            base64_decode($encrypted,true),
            'AES-128-CBC',
            base64_decode($sessionKey),
            OPENSSL_RAW_DATA,
            base64_decode($iv)
        );
        $decrypted = json_decode($decrypted,true);
        if(empty($decrypted)){
            throw new \Exception('解密数据错误');
        }

        return $decrypted;
    }



    /**
     * 校验access token 是否过期
     * @return mixed
     */
    protected function checkAccessToken()
    {
        try {
            $dir = $this->accessTokenDir;
            if (!is_dir($dir)) mkdir($dir, 0755);
            if (!is_file($this->accessTokenFile)) touch($this->accessTokenFile);

            $accessToken = file_get_contents($this->accessTokenFile);
            $accessToken = $accessToken ? json_decode($accessToken,true) : null;
            if (empty($accessToken) || $accessToken['expires_at'] < time()) {
                $accessToken = $this->getAccessToken();
            }else{
                $accessToken = $accessToken['access_token'];
            }
            return $accessToken;
        } catch (\Exception $e) {

        }
    }



    /**
     * 登陆
     * @param $code
     * @return array
     */
    protected abstract function login($code): array ;

    /**
     * 接口请求
     * @param string $uri
     * @param array  $data
     * @return array
     */
    protected abstract function post($uri = '', $data = []): array ;

    /**
     * 获取Access token
     * @return string
     */
    protected abstract function getAccessToken(): string ;


    /**
     * 创建支付订单
     *
     * @param $outOrderNo
     * @param $totalAmount
     * @param $openId
     * @return array
     */
    abstract public function createOrder($outOrderNo, $totalAmount, $openId): array ;

    /**
     * 设置 access token 目录
     */
    protected abstract function setAccessFileDir(): void;

    /**
     * 设置 access token路径
     */
    protected abstract function setAccessFilePath(): void;

    protected abstract function setNoticeUrl(): void;
}
