<?php namespace Wechat\Api;
use Dever;
use Api\Lib\Platform\Request;
class Receive
{
    # 获取消息
    public function callback()
    {
        $input = Dever::input();
        $input['body'] = file_get_contents('php://input', 'r');
        $this->log($input);

        $test = Dever::input('test');
        if ($test == 1) {
            $input = '{"l":"receive.callback","m":"auth","signature":"60e9631eb2b17edbbe1805dc20733ddd9c29d238","timestamp":"1724457958","nonce":"942288454","encrypt_type":"aes","msg_signature":"fbaf4080e53d54253cd898644f56535b3e81e64f","body":"<xml>\n    <AppId><![CDATA[wxa787f5f39aa0598c]]></AppId>\n    <Encrypt><![CDATA[289f2UFxfqOMRCkY6dF4L7b0RuTcVxcKGVEZU3nhJHuTlgA2uvDrTV5YhppDyoJYGIFf2KenpUB4Xg+1wYefxLnYGV8UyJMVZIzlLyPFWMgV8Jw+ElwN2vogPvJ+ceXwDdpzPcLuf7h9MPoedlQqh9Kv0wjjJ6wX8M9i4GZQjYhKWWCcj6hgyymt4eTPJmJ4cYh+X4a2v883Srt581uQSOa+lAv8jbvtYRVk/23qRn5FsOSeIzzGgoj0o4VGZx/muOl0kMQI8B5lZDKCtCeSljWj14c6UQ/5OQh2M22LYLi3PcE3zcoDa5cOni5adUPQQX5sWoAsRBj9U6K+idvG88XLLutA/kM4F+MaX1lcBMhq49DTN2I3qZRzddPdutZi70E/+A7ou9zzZUArgDuuCz35P40/BFGoS8dh9rGXvDfnYlS549XJ0J4fJ14X12q7LImBvr61ugNKFTMGJapgJg==]]></Encrypt>\n</xml>\n"}';
            $input = Dever::json_decode($input);
        }
        $input['body'] = (array) simplexml_load_string($input['body'], null, LIBXML_NOCDATA);
        $input = array_merge($input, $input['body']);
        $api = Dever::load('account', 'api')->run('wechat_open', 'msg', $input, 1, 'setting');
        $request = new Request($api->field, $api->platform['id'], $api->type, $api->info['id']);
        $body = $request->body();
        if ($body['sign'] != $input['msg_signature']) {
            Dever::error('签名验证失败');
        }
        #$input['Encrypt'] = base64_decode($input['Encrypt']);
        $api->field->key = base64_decode($api->field->key . '=');
        $iv = substr($api->field->key, 0, 16);     

        $input['Encrypt'] = str_replace(' ', '+', $input['Encrypt']);

        $body = openssl_decrypt($input['Encrypt'], 'AES-256-CBC', substr($api->field->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
        $pkc_encoder = new PKCS7Encoder;
        $body = $pkc_encoder->decode($body);

        if (strlen($body) < 16)
            Dever::error('解密失败');

        $body = substr($body, 16, strlen($body));
        $len_list = unpack("N", substr($body, 0, 4));
        $xml_len = $len_list[1];
        $xml_content = substr($body, 4, $xml_len);
        $appid = substr($body, $xml_len + 4);
        if ($appid != $api->field->appid) {
            Dever::error('第三方平台配置错误');
        }
        $body = (array) simplexml_load_string($xml_content, null, LIBXML_NOCDATA);
        $m = $input['m'];
        if ($m == 'auth') {
            # 权限
            $this->auth($body);
        } else {
            $this->msg($m, $body);
        }
        echo 'success';die;
    }

    # 获取权限信息
    private function auth($body)
    {
        if (isset($body['ComponentVerifyTicket'])) {
            Dever::load('info', 'wechat')->up(false, 'component_verify_ticket', $body['ComponentVerifyTicket'], 12*3600);
        }
    }

    # 获取消息
    private function msg($m, $body)
    {
        list($method, $appid) = explode('/', $m);
    }

    # 记录日志
    private function log($log)
    {
        return Dever::log($log, 'wechat');
    }
}

/**
 * PKCS7Encoder class
 *
 * 提供基于PKCS7算法的加解密接口.
 */
class PKCS7Encoder
{
    public static $block_size = 32;

    /**
     * 对需要加密的明文进行填充补位
     * @param $text 需要进行填充补位操作的明文
     * @return 补齐明文字符串
     */
    function encode($text)
    {
        $block_size = PKCS7Encoder::$block_size;
        $text_length = strlen($text);
        //计算需要填充的位数
        $amount_to_pad = PKCS7Encoder::$block_size - ($text_length % PKCS7Encoder::$block_size);
        if ($amount_to_pad == 0) {
            $amount_to_pad = PKCS7Encoder::block_size;
        }
        //获得补位所用的字符
        $pad_chr = chr($amount_to_pad);
        $tmp = "";
        for ($index = 0; $index < $amount_to_pad; $index++) {
            $tmp .= $pad_chr;
        }
        return $text . $tmp;
    }

    /**
     * 对解密后的明文进行补位删除
     * @param decrypted 解密后的明文
     * @return 删除填充补位后的明文
     */
    function decode($text)
    {

        $pad = ord(substr($text, -1));
        if ($pad < 1 || $pad > 32) {
            $pad = 0;
        }
        return substr($text, 0, (strlen($text) - $pad));
    }

}