Completed
Pull Request — master (#398)
by Carlos
06:46 queued 03:21
created

Payment::configForJSSDKPayment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.6666
cc 1
eloc 5
nc 1
nop 1
crap 1
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
/**
13
 * Payment.php.
14
 *
15
 * @author    overtrue <[email protected]>
16
 * @copyright 2015 overtrue <[email protected]>
17
 *
18
 * @link      https://github.com/overtrue
19
 * @link      http://overtrue.me
20
 */
21
namespace EasyWeChat\Payment;
22
23
use EasyWeChat\Core\Exceptions\FaultException;
24
use EasyWeChat\Support\Url as UrlHelper;
25
use EasyWeChat\Support\XML;
26
use Overtrue\Socialite\AccessTokenInterface;
27
use Symfony\Component\HttpFoundation\Response;
28
29
/**
30
 * Class Payment.
31
 */
32
class Payment
33
{
34
    /**
35
     * Scheme base path.
36
     */
37
    const SCHEME_PATH = 'weixin://wxpay/bizpayurl';
38
39
    /**
40
     * @var API
41
     */
42
    protected $api;
43
44
    /**
45
     * Merchant instance.
46
     *
47
     * @var \EasyWeChat\Payment\Merchant
48
     */
49
    protected $merchant;
50
51
    /**
52
     * Constructor.
53
     *
54
     * @param Merchant $merchant
55
     */
56 9
    public function __construct(Merchant $merchant)
57
    {
58 9
        $this->merchant = $merchant;
59 9
    }
60
61
    /**
62
     * Build payment scheme for product.
63
     *
64
     * @param string $productId
65
     *
66
     * @return string
67
     */
68 1
    public function scheme($productId)
69
    {
70
        $params = [
71 1
            'appid' => $this->merchant->app_id,
72 1
            'mch_id' => $this->merchant->merchant_id,
73 1
            'time_stamp' => time(),
74 1
            'nonce_str' => uniqid(),
75 1
            'product_id' => $productId,
76 1
        ];
77
78 1
        $params['sign'] = generate_sign($params, $this->merchant->key, 'md5');
79
80 1
        return self::SCHEME_PATH.'?'.http_build_query($params);
81
    }
82
83
    /**
84
     * Handle payment notify.
85
     *
86
     * @param callable $callback
87
     *
88
     * @return Response
89
     */
90 2
    public function handleNotify(callable $callback)
91
    {
92 2
        $notify = $this->getNotify();
93
94 2
        if (!$notify->isValid()) {
95 1
            throw new FaultException('Invalid request XML.', 400);
96
        }
97
98 1
        $notify = $notify->getNotify();
99 1
        $successful = $notify->get('result_code') === 'SUCCESS';
100
101 1
        $handleResult = call_user_func_array($callback, [$notify, $successful]);
102
103 1
        if (is_bool($handleResult) && $handleResult) {
104
            $response = [
105 1
                'return_code' => 'SUCCESS',
106 1
                'return_msg' => 'OK',
107 1
            ];
108 1
        } else {
109
            $response = [
110 1
                'return_code' => 'FAIL',
111 1
                'return_msg' => $handleResult,
112 1
            ];
113
        }
114
115 1
        return new Response(XML::build($response));
116
    }
117
118
    /**
119
     * [WeixinJSBridge] Generate js config for payment.
120
     *
121
     * <pre>
122
     * WeixinJSBridge.invoke(
123
     *  'getBrandWCPayRequest',
124
     *  ...
125
     * );
126
     * </pre>
127
     *
128
     * @param string $prepayId
129
     * @param bool   $json
130
     *
131
     * @return string|array
132
     */
133 2
    public function configForPayment($prepayId, $json = true)
134
    {
135
        $params = [
136 2
            'appId' => $this->merchant->app_id,
137 2
            'timeStamp' => strval(time()),
138 2
            'nonceStr' => uniqid(),
139 2
            'package' => "prepay_id=$prepayId",
140 2
            'signType' => 'MD5',
141 2
        ];
142
143 2
        $params['paySign'] = generate_sign($params, $this->merchant->key, 'md5');
144
145 2
        return $json ? json_encode($params) : $params;
146
    }
147
148
    /**
149
     * [JSSDK] Generate js config for payment.
150
     *
151
     * <pre>
152
     * wx.chooseWXPay({...});
153
     * </pre>
154
     *
155
     * @param string $prepayId
156
     *
157
     * @return array|string
158
     */
159 1
    public function configForJSSDKPayment($prepayId)
160
    {
161 1
        $config = $this->configForPayment($prepayId, false);
162
163 1
        $config['timestamp'] = $config['timeStamp'];
164 1
        unset($config['timeStamp']);
165
166 1
        return $config;
167
    }
168
169
    /**
170
     * Generate app payment parameters.
171
     *
172
     * @param string $prepayId
173
     *
174
     * @return array
175
     */
176 1
    public function configForAppPayment($prepayId)
177
    {
178
        $params = [
179 1
            'appid' => $this->merchant->app_id,
180 1
            'partnerid' => $this->merchant->merchant_id,
181 1
            'prepayid' => $prepayId,
182 1
            'noncestr' => uniqid(),
183 1
            'timestamp' => time(),
184 1
            'package' => 'Sign=WXPay',
185 1
        ];
186
187 1
        $params['sign'] = generate_sign($params, $this->merchant->key);
188
189 1
        return $params;
190
    }
191
192
    /**
193
     * Generate js config for share user address.
194
     *
195
     * @param string|\Overtrue\Socialite\AccessTokenInterface $accessToken
196
     * @param bool                                            $json
197
     *
198
     * @return string|array
199
     */
200 1
    public function configForShareAddress($accessToken, $json = true)
201
    {
202 1
        if ($accessToken instanceof AccessTokenInterface) {
203 1
            $accessToken = $accessToken->getToken();
204 1
        }
205
206
        $params = [
207 1
            'appId' => $this->merchant->app_id,
208 1
            'scope' => 'jsapi_address',
209 1
            'timeStamp' => strval(time()),
210 1
            'nonceStr' => uniqid(),
211 1
            'signType' => 'SHA1',
212 1
        ];
213
214
        $signParams = [
215 1
            'appid' => $params['appId'],
216 1
            'url' => UrlHelper::current(),
217 1
            'timestamp' => $params['timeStamp'],
218 1
            'noncestr' => $params['nonceStr'],
219 1
            'accesstoken' => strval($accessToken),
220 1
        ];
221
222 1
        ksort($signParams);
223
224 1
        $params['addrSign'] = sha1(urldecode(http_build_query($signParams)));
225
226 1
        return $json ? json_encode($params) : $params;
227
    }
228
229
    /**
230
     * Merchant setter.
231
     *
232
     * @param Merchant $merchant
233
     */
234 1
    public function setMerchant(Merchant $merchant)
235
    {
236 1
        $this->merchant = $merchant;
237 1
    }
238
239
    /**
240
     * Merchant getter.
241
     *
242
     * @return Merchant
243
     */
244 1
    public function getMerchant()
245
    {
246 1
        return $this->merchant;
247
    }
248
249
    /**
250
     * Return Notify instance.
251
     *
252
     * @return \EasyWeChat\Payment\Notify
253
     */
254 1
    public function getNotify()
255
    {
256 1
        return new Notify($this->merchant);
257
    }
258
259
    /**
260
     * API setter.
261
     *
262
     * @param API $api
263
     */
264 1
    public function setAPI(API $api)
265
    {
266 1
        $this->api = $api;
267 1
    }
268
269
    /**
270
     * Return API instance.
271
     *
272
     * @return API
273
     */
274 1
    public function getAPI()
275
    {
276 1
        return $this->api ?: $this->api = new API($this->getMerchant());
277
    }
278
279
    /**
280
     * Magic call.
281
     *
282
     * @param string $method
283
     * @param array  $args
284
     *
285
     * @return mixed
286
     *
287
     * @codeCoverageIgnore
288
     */
289
    public function __call($method, $args)
290
    {
291
        if (is_callable([$this->getAPI(), $method])) {
292
            return call_user_func_array([$this->api, $method], $args);
293
        }
294
    }
295
}
296