Passed
Push — master ( be4655...e9d8d4 )
by Carlos
03:27
created

Application::verifySignature()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 10
c 0
b 0
f 0
nc 5
nop 1
dl 0
loc 19
ccs 11
cts 11
cp 1
crap 5
rs 9.6111
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace EasyWeChat\MicroMerchant;
13
14
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
15
use EasyWeChat\Kernel\ServiceContainer;
16
use EasyWeChat\Kernel\Support;
17
use EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException;
18
19
/**
20
 * Class Application.
21
 *
22
 * @author liuml <[email protected]>
23
 *
24
 * @property \EasyWeChat\MicroMerchant\Certficates\Client    $certficates
25
 * @property \EasyWeChat\MicroMerchant\Material\Client       $material
26
 * @property \EasyWeChat\MicroMerchant\MerchantConfig\Client $merchantConfig
27
 * @property \EasyWeChat\MicroMerchant\Withdraw\Client       $withdraw
28
 * @property \EasyWeChat\MicroMerchant\Media\Client          $media
29
 *
30
 * @method mixed submitApplication(array $params)
31
 * @method mixed getStatus(string $applymentId, string $businessCode = '')
32
 * @method mixed upgrade(array $params)
33
 * @method mixed getUpgradeStatus(string $subMchId = '')
34
 */
35
class Application extends ServiceContainer
36
{
37
    /**
38
     * @var array
39
     */
40
    protected $providers = [
41
        // Base services
42
        Base\ServiceProvider::class,
43
        Certficates\ServiceProvider::class,
44
        MerchantConfig\ServiceProvider::class,
45
        Material\ServiceProvider::class,
46
        Withdraw\ServiceProvider::class,
47
        Media\ServiceProvider::class,
48
    ];
49
50
    /**
51
     * @var array
52
     */
53
    protected $defaultConfig = [
54
        'http' => [
55
            'base_uri' => 'https://api.mch.weixin.qq.com/',
56
        ],
57
        'log' => [
58
            'default' => 'dev', // 默认使用的 channel,生产环境可以改为下面的 prod
59
            'channels' => [
60
                // 测试环境
61
                'dev' => [
62
                    'driver' => 'single',
63
                    'path' => '/tmp/easywechat.log',
64
                    'level' => 'debug',
65
                ],
66
                // 生产环境
67
                'prod' => [
68
                    'driver' => 'daily',
69
                    'path' => '/tmp/easywechat.log',
70
                    'level' => 'info',
71
                ],
72
            ],
73
        ],
74
    ];
75
76
    /**
77
     * @return string
78
     *
79
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
80
     */
81 7
    public function getKey()
82
    {
83 7
        $key = $this['config']->key;
84
85 7
        if (empty($key)) {
86
            throw new InvalidArgumentException('config key connot be empty.');
87
        }
88
89 7
        if (32 !== strlen($key)) {
90 1
            throw new InvalidArgumentException(sprintf("'%s' should be 32 chars length.", $key));
91
        }
92
93 7
        return $key;
94
    }
95
96
    /**
97
     * set sub-mch-id and appid.
98
     *
99
     * @param string $subMchId Identification Number of Small and Micro Businessmen Reported by Service Providers
100
     * @param string $appId    Public Account ID of Service Provider
101
     *
102
     * @return $this
103
     */
104 1
    public function setSubMchId(string $subMchId, string $appId = '')
105
    {
106 1
        $this['config']->set('sub_mch_id', $subMchId);
107 1
        $this['config']->set('appid', $appId);
108
109 1
        return $this;
110
    }
111
112
    /**
113
     * setCertificate.
114
     *
115
     * @param string $certificate
116
     * @param string $serialNo
117
     *
118
     * @return $this
119
     */
120
    public function setCertificate(string $certificate, string $serialNo)
121
    {
122
        $this['config']->set('certificate', $certificate);
123
        $this['config']->set('serial_no', $serialNo);
124
125
        return $this;
126
    }
127
128
    /**
129
     * Returning true indicates that the verification is successful,
130
     * returning false indicates that the signature field does not exist or is empty,
131
     * and if the signature verification is wrong, the InvalidSignException will be thrown directly.
132
     *
133
     * @param array $data
134
     *
135
     * @return bool
136
     *
137
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
138
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
139
     */
140 5
    public function verifySignature(array $data)
141
    {
142 5
        if (!isset($data['sign']) || empty($data['sign'])) {
143 5
            return false;
144
        }
145
146 1
        $sign = $data['sign'];
147 1
        unset($data['sign']);
148
149 1
        $signType = strlen($sign) > 32 ? 'HMAC-SHA256' : 'MD5';
150 1
        $secretKey = $this->getKey();
151
152 1
        $encryptMethod = Support\get_encrypt_method($signType, $secretKey);
0 ignored issues
show
Bug introduced by
The function get_encrypt_method was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

152
        $encryptMethod = /** @scrutinizer ignore-call */ Support\get_encrypt_method($signType, $secretKey);
Loading history...
153
154 1
        if (Support\generate_sign($data, $secretKey, $encryptMethod) === $sign) {
0 ignored issues
show
Bug introduced by
The function generate_sign was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

154
        if (/** @scrutinizer ignore-call */ Support\generate_sign($data, $secretKey, $encryptMethod) === $sign) {
Loading history...
155 1
            return true;
156
        }
157
158 1
        throw new InvalidSignException('return value signature verification error');
159
    }
160
161
    /**
162
     * @param string $name
163
     * @param array  $arguments
164
     *
165
     * @return mixed
166
     */
167
    public function __call($name, $arguments)
168
    {
169
        return call_user_func_array([$this['base'], $name], $arguments);
170
    }
171
}
172