Completed
Push — master ( 5535f2...e8b1a1 )
by Songda
02:09
created

Alipay::verify()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 20
rs 8.8571
cc 5
eloc 11
nc 9
nop 3
1
<?php
2
3
namespace Yansongda\Pay\Gateways\Alipay;
4
5
use Yansongda\Pay\Support\Config;
6
use Yansongda\Pay\Traits\HasHttpRequest;
7
use Yansongda\Pay\Contracts\GatewayInterface;
8
use Yansongda\Pay\Exceptions\GatewayException;
9
use Yansongda\Pay\Exceptions\InvalidArgumentException;
10
11
/**
12
 * abstract class Alipay.
13
 */
14
abstract class Alipay implements GatewayInterface
15
{
16
    use HasHttpRequest;
17
18
    /**
19
     * 支付宝支付网关.
20
     *
21
     * @var string
22
     */
23
    protected $gateway = 'https://openapi.alipay.com/gateway.do';
24
25
    /**
26
     * 支付宝公共参数.
27
     *
28
     * @var [type]
29
     */
30
    protected $config;
31
32
    /**
33
     * 用户的传参
34
     *
35
     * @var [type]
36
     */
37
    protected $user_config;
38
39
    /**
40
     * [__construct description].
41
     *
42
     * @author yansongda <[email protected]>
43
     *
44
     * @version 2017-08-14
45
     *
46
     * @param   array      $config [description]
47
     */
48
    public function __construct(array $config)
49
    {
50
        $this->user_config = new Config($config);
51
52
        if (is_null($this->user_config->get('app_id'))) {
53
            throw new InvalidArgumentException("Missing Config -- [app_id]");
54
        }
55
56
        $this->config = [
57
            'app_id' => $this->user_config->get('app_id'),
58
            'method' => '',
59
            'format' => 'JSON',
60
            'charset' => 'utf-8',
61
            'sign_type' => 'RSA2',
62
            'version' => '1.0',
63
            'return_url' => $this->user_config->get('return_url', ''),
64
            'notify_url' => $this->user_config->get('notify_url', ''),
65
            'timestamp' => date('Y-m-d H:i:s'),
66
            'sign' => '',
67
            'biz_content' => '',
68
        ];
69
    }
70
71
72
    /**
73
     * 对外接口 - 支付.
74
     *
75
     * @author yansongda <[email protected]>
76
     *
77
     * @version 2017-08-15
78
     *
79
     * @param   array      $config_biz [description]
80
     *
81
     * @return  [type]                 [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
82
     */
83 View Code Duplication
    public function pay(array $config_biz = [])
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
84
    {
85
        $config_biz['product_code'] = $this->getPayProductCode();
86
87
        $this->config['method'] = $this->getPayMethod();
88
        $this->config['biz_content'] = json_encode($config_biz, JSON_UNESCAPED_UNICODE);
89
        $this->config['sign'] = $this->getSign();
90
91
        return $this->buildPayHtml();
92
    }
93
94
    /**
95
     * 对外接口 - 退款.
96
     *
97
     * @author yansongda <[email protected]>
98
     *
99
     * @version 2017-08-15
100
     *
101
     * @param   array      $config_biz [description]
102
     *
103
     * @return  [type]                 [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
104
     */
105 View Code Duplication
    public function refund(array $config_biz = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
106
    {
107
        $this->config['biz_content'] = json_encode($config_biz, JSON_UNESCAPED_UNICODE);
108
        $this->config['method'] = 'alipay.trade.refund';
109
110
        return $this->getResult('alipay_trade_refund_response');
111
    }
112
113
    /**
114
     * 对外接口 - 关闭.
115
     *
116
     * @author yansongda <[email protected]>
117
     *
118
     * @version 2017-08-15
119
     *
120
     * @param   array      $config_biz [description]
121
     *
122
     * @return  [type]                 [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
123
     */
124 View Code Duplication
    public function close(array $config_biz = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
    {
126
        $this->config['biz_content'] = json_encode($config_biz, JSON_UNESCAPED_UNICODE);
127
        $this->config['method'] = 'alipay.trade.close';
128
129
        return $this->getResult('alipay_trade_close_response');
130
    }
131
132
    /**
133
     * 对外接口 - 验证.
134
     *
135
     * @author yansongda <[email protected]>
136
     *
137
     * @version 2017-08-11
138
     *
139
     * @param   array      $data 待签名数组
140
     * @param   string     $sign 签名字符串-支付宝服务器发送过来的原始串
141
     * @param   bool       $sync 是否同步验证
142
     *
143
     * @return  [type]           [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
144
     */
145
    public function verify($data, $sign = null, $sync = false)
146
    {
147
        if (is_null($this->user_config->get('ali_public_key'))) {
148
            throw new InvalidArgumentException("Missing Config -- [ali_public_key]");
149
        }
150
151
        $sign = is_null($sign) ? $data['sign'] : $sign;
152
153
        $res = "-----BEGIN PUBLIC KEY-----\n" .
154
                wordwrap($this->user_config->get('ali_public_key'), 64, "\n", true) .
155
                "\n-----END PUBLIC KEY-----";
156
157
        $data = $sync ? json_encode($data, JSON_UNESCAPED_UNICODE) : $this->getSignContent($data, true);
158
        
159
        if (openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256) === 1) {
160
            return true;
161
        }
162
163
        return false;
164
    }
165
166
    /**
167
     * [getMethod description].
168
     *
169
     * @author yansongda <[email protected]>
170
     *
171
     * @version 2017-08-10
172
     *
173
     * @return  [type]     [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
174
     */
175
    abstract protected function getPayMethod();
176
177
    /**
178
     * [getProductCode description].
179
     *
180
     * @author yansongda <[email protected]>
181
     *
182
     * @version 2017-08-10
183
     *
184
     * @return  [type]     [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
185
     */
186
    abstract protected function getPayProductCode();
187
188
    /**
189
     * [buildHtmlPay description]
190
     *
191
     * @author yansongda <[email protected]>
192
     *
193
     * @version 2017-08-11
194
     *
195
     * @return  [type]     [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
196
     */
197
    protected function buildPayHtml()
198
    {
199
        $sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gateway."?charset=utf-8' method='POST'>";
200
        while (list ($key, $val) = each ($this->config)) {
201
            $val = str_replace("'","&apos;",$val);
202
            $sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
203
        }
204
        $sHtml = $sHtml."<input type='submit' value='ok' style='display:none;''></form>";
205
        $sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
206
        
207
        return $sHtml;
208
    }
209
210
    /**
211
     * get alipay api result.
212
     *
213
     * @author yansongda <[email protected]>
214
     *
215
     * @version 2017-08-12
216
     *
217
     * @param   [type]     $method [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
218
     *
219
     * @return  [type]             [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
220
     */
221
    protected function getResult($method)
222
    {
223
        $this->config['sign'] = $this->getSign();
224
        
225
        $data = json_decode($this->post($this->gateway, $this->config), true);
226
227
        if (! isset($data[$method]['code']) || $data[$method]['code'] !== '10000') {
228
            throw new GatewayException(
229
                'get result error:' . $data[$method]['msg'] . ' - ' . $data[$method]['sub_msg'],
230
                $data[$method]['code'],
231
                $data);
232
        }
233
234
        return $this->verify($data[$method], $data['sign'], true);
235
    }
236
237
    /**
238
     * 签名.
239
     *
240
     * @author yansongda <[email protected]>
241
     *
242
     * @version 2017-08-10
243
     *
244
     * @return  [type]     [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
245
     */
246
    protected function getSign()
247
    {
248
        if (is_null($this->user_config->get('private_key'))) {
249
            throw new InvalidArgumentException("Missing Config -- [private_key]");
250
        }
251
252
        $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
253
                wordwrap($this->user_config->get('private_key'), 64, "\n", true) .
254
                "\n-----END RSA PRIVATE KEY-----";
255
256
        openssl_sign($this->getSignContent($this->config), $sign, $res, OPENSSL_ALGO_SHA256);
257
258
        return base64_encode($sign);
259
    }
260
261
    /**
262
     * 待签名数组.
263
     *
264
     * @author yansongda <[email protected]>
265
     *
266
     * @version 2017-08-11
267
     *
268
     * @param   array      $toBeSigned [description]
269
     * @param   boolean    $verify     是否异步同时验证签名
270
     *
271
     * @return  [type]                 [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
272
     */
273
    protected function getSignContent(array $toBeSigned, $verify = false)
274
    {
275
        ksort($toBeSigned);
276
277
        $stringToBeSigned = "";
278
        foreach ($toBeSigned as $k => $v) {
279
            if ($verify && $k != 'sign' && $k != 'sign_type') {
280
                $stringToBeSigned .= $k . "=" . $v . "&";
281
            }
282
            if (!$verify && $v !== '' && !is_null($v) && $k != 'sign' && "@" != substr($v, 0, 1)) {
283
                $stringToBeSigned .= $k . "=" . $v . "&";
284
            }
285
        }
286
        $stringToBeSigned = substr($stringToBeSigned, 0, -1);
287
        unset ($k, $v);
288
289
        return $stringToBeSigned;
290
    }
291
292
}
293