Issues (14)

src/Provider/FFIProvider.php (10 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
namespace tinymeng\WeWorkFinanceSDK\Provider;
5
6
use FFI;
7
use tinymeng\WeWorkFinanceSDK\Contract\ProviderInterface;
8
use tinymeng\WeWorkFinanceSDK\Exception\FinanceSDKException;
9
use tinymeng\WeWorkFinanceSDK\Exception\InvalidArgumentException;
10
11
/**
12
 * FFIProvider
13
 * @author: TinyMeng <[email protected]>
14
 */
15
class FFIProvider extends AbstractProvider
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $config = [];
21
22
    /**
23
     * @var FFI
24
     */
25
    private $ffi;
26
27
    /**
28
     * @var string 指针
29
     */
30
    private $financeSdk;
31
32
    /**
33
     * @var string C语言头
34
     */
35
    private $cHeader = 'WeWorkFinanceSdk_C.h';
36
37
    /**
38
     * @var string C语言库
39
     */
40
    private $cLib = 'libWeWorkFinanceSdk_C.so';
41
42
    public function __destruct()
43
    {
44
        // 释放sdk
45
        $this->financeSdk instanceof FFI && $this->ffi->DestroySdk($this->financeSdk);
0 ignored issues
show
The method DestroySdk() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

45
        $this->financeSdk instanceof FFI && $this->ffi->/** @scrutinizer ignore-call */ DestroySdk($this->financeSdk);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function setConfig(array $config): ProviderInterface
52
    {
53
        $this->config = array_merge($this->config, $config);
54
        $this->setFinanceSDK();
55
        return $this;
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function getConfig(): array
62
    {
63
        return $this->config;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     * @throws FinanceSDKException ...
69
     */
70
    public function getChatData(int $seq, int $limit, int $timeout = 0): string
71
    {
72
        // 初始化buffer
73
        $chatDatas = $this->ffi->NewSlice();
0 ignored issues
show
The method NewSlice() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
        /** @scrutinizer ignore-call */ 
74
        $chatDatas = $this->ffi->NewSlice();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
74
        // 拉取内容
75
        $res = $this->ffi->GetChatData($this->financeSdk, $seq, $limit, $this->config['proxy'], $this->config['passwd'], $this->config['timeout'], $chatDatas);
0 ignored issues
show
The method GetChatData() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

75
        /** @scrutinizer ignore-call */ 
76
        $res = $this->ffi->GetChatData($this->financeSdk, $seq, $limit, $this->config['proxy'], $this->config['passwd'], $this->config['timeout'], $chatDatas);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
76
        if ($res !== 0) {
77
            throw new FinanceSDKException(sprintf('GetChatData err res:%d', $res));
78
        }
79
80
        $resStr = FFI::string($chatDatas->buf);
81
        // 释放buffer
82
        $this->ffi->FreeSlice($chatDatas);
0 ignored issues
show
The method FreeSlice() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
        $this->ffi->/** @scrutinizer ignore-call */ 
83
                    FreeSlice($chatDatas);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
83
        $chatDatas->len = 0;
84
        return $resStr;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     * @throws FinanceSDKException ...
90
     */
91
    public function decryptData(string $randomKey, string $encryptStr): string
92
    {
93
        // 初始化buffer
94
        $msg = $this->ffi->NewSlice();
95
        $res = $this->ffi->DecryptData($randomKey, $encryptStr, $msg);
0 ignored issues
show
The method DecryptData() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
        /** @scrutinizer ignore-call */ 
96
        $res = $this->ffi->DecryptData($randomKey, $encryptStr, $msg);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
96
        if ($res !== 0) {
97
            throw new FinanceSDKException(sprintf('RsaDecryptChatData err res:%d', $res));
98
        }
99
        $resStr = FFI::string($msg->buf);
100
        // 释放buffer
101
        $this->ffi->FreeSlice($msg);
102
        $msg->len = 0;
103
        return $resStr;
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     * @throws FinanceSDKException
109
     */
110
    public function getMediaData(string $sdkFileId, string $path): \SplFileInfo
111
    {
112
        try {
113
            $this->downloadMediaData($sdkFileId, $path);
114
        } catch (\Exception $e) {
115
            throw new FinanceSDKException('获取文件失败' . $e->getMessage(), $e->getCode());
116
        }
117
        return new \SplFileInfo($path);
118
    }
119
120
    /**
121
     * 下载媒体资源.
122
     * @param string $sdkFileId file id
123
     * @param string $path 文件路径
124
     * @throws FinanceSDKException
125
     */
126
    protected function downloadMediaData(string $sdkFileId, string $path): void
127
    {
128
        $indexBuf = '';
129
130
        while (true) {
131
            // 初始化buffer MediaData_t*
132
            $media = $this->ffi->NewMediaData();
0 ignored issues
show
The method NewMediaData() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

132
            /** @scrutinizer ignore-call */ 
133
            $media = $this->ffi->NewMediaData();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
133
134
            // 拉取内容
135
            $res = $this->ffi->GetMediaData($this->financeSdk, $indexBuf, $sdkFileId, $this->config['proxy'], $this->config['passwd'], $this->config['timeout'], $media);
0 ignored issues
show
The method GetMediaData() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
            /** @scrutinizer ignore-call */ 
136
            $res = $this->ffi->GetMediaData($this->financeSdk, $indexBuf, $sdkFileId, $this->config['proxy'], $this->config['passwd'], $this->config['timeout'], $media);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
136
            if ($res !== 0) {
137
                $this->ffi->FreeMediaData($media);
0 ignored issues
show
The method FreeMediaData() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
                $this->ffi->/** @scrutinizer ignore-call */ 
138
                            FreeMediaData($media);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
138
                throw new FinanceSDKException(sprintf('GetMediaData err res:%d\n', $res));
139
            }
140
141
            // buffer写入文件
142
            $handle = fopen($path, 'ab+');
143
            if (! $handle) {
144
                throw new \RuntimeException(sprintf('打开文件失败:%s', $path));
145
            }
146
147
            fwrite($handle, FFI::string($media->data, $media->data_len), $media->data_len);
148
            fclose($handle);
149
150
            // 完成下载
151
            if ($media->is_finish === 1) {
152
                $this->ffi->FreeMediaData($media);
153
                break;
154
            }
155
156
            // 重置文件指针
157
            $indexBuf = FFI::string($media->outindexbuf);
158
            $this->ffi->FreeMediaData($media);
159
        }
160
    }
161
162
    /**
163
     * 获取php-ext-sdk.
164
     * @param array $config ...
165
     * @throws FinanceSDKException ...
166
     * @throws InvalidArgumentException ...
167
     */
168
    protected function setFinanceSDK(array $config = []): void
169
    {
170
        if (! extension_loaded('ffi')) {
171
            throw new FinanceSDKException('缺少ext-ffi扩展');
172
        }
173
174
        $this->config = array_merge($this->config, $config);
175
        if (! isset($this->config['corpid'])) {
176
            throw new InvalidArgumentException('缺少配置:corpid');
177
        }
178
        if (! isset($this->config['secret'])) {
179
            throw new InvalidArgumentException('缺少配置:secret');
180
        }
181
182
        isset($this->config['proxy']) || $this->config['proxy']     = '';
183
        isset($this->config['passwd']) || $this->config['passwd']   = '';
184
        isset($this->config['timeout']) || $this->config['timeout'] = '';
185
186
        // C包路径
187
        if(empty($this->config['includePath'])){
188
            $includePath   = dirname(__DIR__, 2) . '/include/';
189
        }else{
190
            $includePath   = $this->config['includePath'];
191
        }
192
        $this->cHeader = $includePath . $this->cHeader;
193
        $this->cLib    = $includePath . $this->cLib;
194
195
        // 引入ffi
196
        $this->ffi = FFI::cdef(file_get_contents($this->cHeader), $this->cLib);
197
198
        // WeWorkFinanceSdk_t* sdk
199
        $this->financeSdk = $this->ffi->NewSdk();
0 ignored issues
show
The method NewSdk() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

199
        /** @scrutinizer ignore-call */ 
200
        $this->financeSdk = $this->ffi->NewSdk();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
200
201
        // 初始化
202
        $res = $this->ffi->Init($this->financeSdk, $this->config['corpid'], $this->config['secret']);
0 ignored issues
show
The method Init() does not exist on FFI. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

202
        /** @scrutinizer ignore-call */ 
203
        $res = $this->ffi->Init($this->financeSdk, $this->config['corpid'], $this->config['secret']);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
203
        if ($res !== 0) {
204
            throw new FinanceSDKException('ffi:Init() 初始化错误');
205
        }
206
    }
207
}
208