1 | <?php |
||
35 | class Payment |
||
36 | { |
||
37 | /** |
||
38 | * Scheme base path. |
||
39 | */ |
||
40 | const SCHEME_PATH = 'weixin://wxpay/bizpayurl'; |
||
41 | |||
42 | /** |
||
43 | * @var API |
||
44 | */ |
||
45 | protected $api; |
||
46 | |||
47 | /** |
||
48 | * Merchant instance. |
||
49 | * |
||
50 | * @var \EasyWeChat\Payment\Merchant |
||
51 | */ |
||
52 | protected $merchant; |
||
53 | |||
54 | /** |
||
55 | * Constructor. |
||
56 | * |
||
57 | * @param Merchant $merchant |
||
58 | */ |
||
59 | 10 | public function __construct(Merchant $merchant) |
|
63 | |||
64 | /** |
||
65 | * Build payment scheme for product. |
||
66 | * |
||
67 | * @param string $productId |
||
68 | * |
||
69 | * @return string |
||
70 | */ |
||
71 | 1 | public function scheme($productId) |
|
85 | |||
86 | /** |
||
87 | * Handle payment notify. |
||
88 | * |
||
89 | * @param callable $callback |
||
90 | * |
||
91 | * @return Response |
||
92 | */ |
||
93 | 2 | public function handleNotify(callable $callback) |
|
120 | |||
121 | /** |
||
122 | * Handle native scan notify. |
||
123 | * https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 |
||
124 | * The callback shall return string of prepay_id or throw an exception. |
||
125 | * |
||
126 | * @param callable $callback |
||
127 | * |
||
128 | * @return Response |
||
129 | */ |
||
130 | 1 | public function handleScanNotify(callable $callback) |
|
131 | { |
||
132 | 1 | $notify = $this->getNotify(); |
|
133 | |||
134 | 1 | if (!$notify->isValid()) { |
|
135 | throw new FaultException('Invalid request payloads.', 400); |
||
136 | } |
||
137 | |||
138 | 1 | $notify = $notify->getNotify(); |
|
139 | |||
140 | try { |
||
141 | 1 | $prepayId = call_user_func_array($callback, [$notify->get('product_id'), $notify->get('openid'), $notify]); |
|
142 | $response = [ |
||
143 | 1 | 'return_code' => 'SUCCESS', |
|
144 | 1 | 'appid' => $this->merchant->app_id, |
|
145 | 1 | 'mch_id' => $this->merchant->merchant_id, |
|
146 | 1 | 'nonce_str' => uniqid(), |
|
147 | 1 | 'prepay_id' => strval($prepayId), |
|
148 | 1 | 'result_code' => 'SUCCESS', |
|
149 | 1 | ]; |
|
150 | 1 | $response['sign'] = generate_sign($response, $this->merchant->key); |
|
151 | 1 | } catch (\Exception $e) { |
|
152 | $response = [ |
||
153 | 1 | 'return_code' => 'SUCCESS', |
|
154 | 1 | 'return_msg' => $e->getCode(), |
|
155 | 1 | 'result_code' => 'FAIL', |
|
156 | 1 | 'err_code_des' => $e->getMessage(), |
|
157 | 1 | ]; |
|
158 | } |
||
159 | |||
160 | 1 | return new Response(XML::build($response)); |
|
161 | } |
||
162 | |||
163 | /** |
||
164 | * [WeixinJSBridge] Generate js config for payment. |
||
165 | * |
||
166 | * <pre> |
||
167 | * WeixinJSBridge.invoke( |
||
168 | * 'getBrandWCPayRequest', |
||
169 | * ... |
||
170 | * ); |
||
171 | * </pre> |
||
172 | * |
||
173 | * @param string $prepayId |
||
174 | * @param bool $json |
||
175 | * |
||
176 | * @return string|array |
||
177 | */ |
||
178 | 2 | public function configForPayment($prepayId, $json = true) |
|
192 | |||
193 | /** |
||
194 | * [JSSDK] Generate js config for payment. |
||
195 | * |
||
196 | * <pre> |
||
197 | * wx.chooseWXPay({...}); |
||
198 | * </pre> |
||
199 | * |
||
200 | * @param string $prepayId |
||
201 | * |
||
202 | * @return array|string |
||
203 | */ |
||
204 | 1 | public function configForJSSDKPayment($prepayId) |
|
205 | { |
||
206 | 1 | $config = $this->configForPayment($prepayId, false); |
|
207 | |||
208 | 1 | $config['timestamp'] = $config['timeStamp']; |
|
209 | 1 | unset($config['timeStamp']); |
|
210 | |||
211 | 1 | return $config; |
|
212 | } |
||
213 | |||
214 | /** |
||
215 | * Generate app payment parameters. |
||
216 | * |
||
217 | * @param string $prepayId |
||
218 | * |
||
219 | * @return array |
||
220 | */ |
||
221 | 2 | public function configForAppPayment($prepayId) |
|
222 | { |
||
223 | $params = [ |
||
224 | 2 | 'appid' => $this->merchant->app_id, |
|
225 | 1 | 'partnerid' => $this->merchant->merchant_id, |
|
226 | 1 | 'prepayid' => $prepayId, |
|
227 | 1 | 'noncestr' => uniqid(), |
|
228 | 1 | 'timestamp' => time(), |
|
229 | 1 | 'package' => 'Sign=WXPay', |
|
230 | 1 | ]; |
|
231 | |||
232 | 1 | $params['sign'] = generate_sign($params, $this->merchant->key); |
|
233 | |||
234 | 1 | return $params; |
|
235 | } |
||
236 | |||
237 | /** |
||
238 | * Generate js config for share user address. |
||
239 | * |
||
240 | * @param string|\Overtrue\Socialite\AccessTokenInterface $accessToken |
||
241 | * @param bool $json |
||
242 | * |
||
243 | * @return string|array |
||
244 | */ |
||
245 | 1 | public function configForShareAddress($accessToken, $json = true) |
|
246 | { |
||
247 | 1 | if ($accessToken instanceof AccessTokenInterface) { |
|
248 | 1 | $accessToken = $accessToken->getToken(); |
|
249 | 1 | } |
|
250 | |||
251 | $params = [ |
||
252 | 1 | 'appId' => $this->merchant->app_id, |
|
253 | 1 | 'scope' => 'jsapi_address', |
|
254 | 1 | 'timeStamp' => strval(time()), |
|
255 | 1 | 'nonceStr' => uniqid(), |
|
256 | 1 | 'signType' => 'SHA1', |
|
257 | 1 | ]; |
|
258 | |||
259 | $signParams = [ |
||
260 | 1 | 'appid' => $params['appId'], |
|
261 | 1 | 'url' => UrlHelper::current(), |
|
262 | 1 | 'timestamp' => $params['timeStamp'], |
|
263 | 1 | 'noncestr' => $params['nonceStr'], |
|
264 | 1 | 'accesstoken' => strval($accessToken), |
|
265 | 1 | ]; |
|
266 | |||
267 | 1 | ksort($signParams); |
|
268 | |||
269 | 1 | $params['addrSign'] = sha1(urldecode(http_build_query($signParams))); |
|
270 | |||
271 | 1 | return $json ? json_encode($params) : $params; |
|
272 | } |
||
273 | |||
274 | /** |
||
275 | * Merchant setter. |
||
276 | * |
||
277 | * @param Merchant $merchant |
||
278 | */ |
||
279 | 1 | public function setMerchant(Merchant $merchant) |
|
280 | { |
||
281 | 1 | $this->merchant = $merchant; |
|
282 | 1 | } |
|
283 | |||
284 | /** |
||
285 | * Merchant getter. |
||
286 | * |
||
287 | * @return Merchant |
||
288 | */ |
||
289 | 1 | public function getMerchant() |
|
290 | { |
||
291 | 1 | return $this->merchant; |
|
292 | } |
||
293 | |||
294 | /** |
||
295 | * Return Notify instance. |
||
296 | * |
||
297 | * @return \EasyWeChat\Payment\Notify |
||
298 | */ |
||
299 | 1 | public function getNotify() |
|
300 | { |
||
301 | 1 | return new Notify($this->merchant); |
|
302 | } |
||
303 | |||
304 | /** |
||
305 | * API setter. |
||
306 | * |
||
307 | * @param API $api |
||
308 | */ |
||
309 | 1 | public function setAPI(API $api) |
|
310 | { |
||
311 | 1 | $this->api = $api; |
|
312 | 1 | } |
|
313 | |||
314 | /** |
||
315 | * Return API instance. |
||
316 | * |
||
317 | * @return API |
||
318 | */ |
||
319 | 1 | public function getAPI() |
|
320 | { |
||
321 | 1 | return $this->api ?: $this->api = new API($this->getMerchant()); |
|
322 | } |
||
323 | |||
324 | /** |
||
325 | * Magic call. |
||
326 | * |
||
327 | * @param string $method |
||
328 | * @param array $args |
||
329 | * |
||
330 | * @return mixed |
||
331 | * |
||
332 | * @codeCoverageIgnore |
||
333 | */ |
||
334 | public function __call($method, $args) |
||
340 | } |
||
341 |