Completed
Push — master ( 102abf...4b0145 )
by Wei
02:46
created

WechatPay::sendRedPack()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 2
nop 11
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @license MIT
4
 * @author zhangv
5
 */
6
namespace zhangv\wechat;
7
8
use \Exception;
9
10
class WechatPay {
11
	const TRADETYPE_JSAPI = 'JSAPI',TRADETYPE_NATIVE = 'NATIVE',TRADETYPE_APP = 'APP',TRADETYPE_MWEB = 'MWEB';
12
	const SIGNTYPE_MD5 = 'MD5', SIGNTYPE_HMACSHA256 = 'HMAC-SHA256';
13
	const CHECKNAME_FORCECHECK = 'FORCE_CHECK',CHECKNAME_NOCHECK = 'NO_CHECK';
14
	const ACCOUNTTYPE_BASIC = 'Basic',ACCOUNTTYPE_OPERATION = 'Operation',ACCOUNTTYPE_FEES = 'Fees';
15
	/** 支付 */
16
	const URL_UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
17
	const URL_ORDERQUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
18
	const URL_CLOSEORDER = 'https://api.mch.weixin.qq.com/pay/closeorder';
19
	const URL_REFUND = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
20
	const URL_REFUNDQUERY = 'https://api.mch.weixin.qq.com/pay/refundquery';
21
	const URL_DOWNLOADBILL = 'https://api.mch.weixin.qq.com/pay/downloadbill';
22
	const URL_DOWNLOAD_FUND_FLOW = 'https://api.mch.weixin.qq.com/pay/downloadfundflow';
23
	const URL_REPORT = 'https://api.mch.weixin.qq.com/payitil/report';
24
	const URL_SHORTURL = 'https://api.mch.weixin.qq.com/tools/shorturl';
25
	const URL_MICROPAY = 'https://api.mch.weixin.qq.com/pay/micropay';
26
	const URL_GETHBINFO = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo';
27
	const URL_BATCHQUERYCOMMENT = 'https://api.mch.weixin.qq.com/billcommentsp/batchquerycomment';
28
	const URL_REVERSE = 'https://api.mch.weixin.qq.com/secapi/pay/reverse';
29
	const URL_AUTHCODETOOPENID = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid';
30
	/** 红包 */
31
	const URL_SENDREDPACK = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
32
	const URL_SENDGROUPREDPACK = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack';
33
	/** 企业付款 */
34
	const URL_TRANSFER_WALLET = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
35
	const URL_QUERY_TRANSFER_WALLET = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo';
36
	const URL_TRANSFER_BANKCARD = 'https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank';
37
	const URL_QUERY_TRANSFER_BANKCARD = 'https://api.mch.weixin.qq.com/mmpaysptrans/query_bank';
38
	/** 代金券 */
39
	const URL_SEND_COUPON = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/send_coupon';
40
	const URL_QUERY_COUPON_STOCK = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/query_coupon_stock';
41
	const URL_QUERY_COUPON_INFO = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/querycouponsinfo';
42
	/** Sandbox获取测试公钥 */
43
	const URL_GETPUBLICKEY = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
44
	public static $BANKCODE = ['工商银行' => '1002', '农业银行' => '1005', '中国银行' => '1026', '建设银行' => '1003', '招商银行' => '1001',
45
		'邮储银行' => '1066', '交通银行' => '1020', '浦发银行' => '1004', '民生银行' => '1006', '兴业银行' => '1009', '平安银行' => '1010',
46
		'中信银行' => '1021', '华夏银行' => '1025', '广发银行' => '1027', '光大银行' => '1022', '北京银行' => '1032', '宁波银行' => '1056',];
47
48
	public $getSignKeyUrl = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey";
49
	public $sandbox = false;
50
51
	/** @var string */
52
	public $returnCode;
53
	/** @var string */
54
	public $returnMsg;
55
	/** @var string */
56
	public $resultCode;
57
	/** @var string */
58
	public $errCode;
59
	/** @var string */
60
	public $errCodeDes;
61
	/** @var string */
62
	public $requestXML = null;
63
	/** @var string */
64
	public $responseXML = null;
65
	/** @var array */
66
	public $requestArray = null;
67
	/** @var array */
68
	public $responseArray = null;
69
	/** @var array */
70
	private $config;
71
	/** @var HttpClient */
72
	private $httpClient = null;
73
	/** @var WechatOAuth */
74
	private $wechatOAuth = null;
75
76
	/**
77
	 * @param $config array 配置
78
	 */
79
	public function __construct(array $config) {
80
		$this->config = $config;
81
		$this->httpClient = new HttpClient(5);
82
	}
83
84
	public function setWechatOAuth($wechatOAuth){
85
		$this->wechatOAuth = $wechatOAuth;
86
	}
87
88
	public function getWechatOAuth(){
89
		if(!$this->wechatOAuth){
90
			$this->wechatOAuth = new WechatOAuth($this->config['app_id'],$this->config['app_secret']);
91
		}
92
		return $this->wechatOAuth;
93
	}
94
95
	public function setConfig($config){
96
		$this->config = $config;
97
	}
98
99
	public function getConfig(){
100
		return $this->config;
101
	}
102
103
	public function setHttpClient($httpClient){
104
		$this->httpClient = $httpClient;
105
	}
106
107
	/**
108
	 * 获取JSAPI(公众号/小程序)的预支付单信息(prepay_id)
109
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
110
	 * @param $body string 内容
111
	 * @param $out_trade_no string 商户订单号
112
	 * @param $total_fee int 总金额
113
	 * @param $openid string openid
114
	 * @param $spbill_create_ip
115
	 * @param $ext array
116
	 * @return string
117
	 * @throws \Exception
118
	 */
119
	public function getPrepayId($body,$out_trade_no,$total_fee,$openid,$spbill_create_ip = null,$ext = null) {
120
		$data = ($ext && is_array($ext))?$ext:array();
121
		$data["body"]         = $body;
122
		$data["out_trade_no"] = $out_trade_no;
123
		$data["total_fee"]    = $total_fee;
124
		$data["spbill_create_ip"] = $spbill_create_ip?:$_SERVER["REMOTE_ADDR"];
125
		$data["notify_url"]   = $this->config["notify_url"];
126
		$data["trade_type"]   = WechatPay::TRADETYPE_JSAPI;
127
		if(!$openid) throw new Exception('openid is required when trade_type is JSAPI');
128
		$data["openid"]   = $openid;
129
		$result = $this->unifiedOrder($data);
130
		return $result["prepay_id"];
131
	}
132
133
	/**
134
	 * 获取APP的的预支付单信息(prepay_id)(注意这里的appid是从开放平台申请的)
135
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
136
	 * @param $body string 内容
137
	 * @param $out_trade_no string 商户订单号
138
	 * @param $total_fee int 总金额
139
	 * @param $spbill_create_ip string 终端ID
140
	 * @param $ext array
141
	 * @return string
142
	 */
143
	public function getPrepayIdAPP($body,$out_trade_no,$total_fee,$spbill_create_ip,$ext = null) {
144
		$data = ($ext && is_array($ext))?$ext:array();
145
		$data["body"]         = $body;
146
		$data["out_trade_no"] = $out_trade_no;
147
		$data["total_fee"]    = $total_fee;
148
		$data["spbill_create_ip"] = $spbill_create_ip;
149
		$data["notify_url"]   = $this->config["notify_url"];
150
		$data["trade_type"]   = WechatPay::TRADETYPE_APP;
151
		$result = $this->unifiedOrder($data);
152
		return $result["prepay_id"];
153
	}
154
155
	/**
156
	 * 扫码支付(模式二)获取支付二维码
157
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
158
	 * @param $body
159
	 * @param $out_trade_no
160
	 * @param $total_fee
161
	 * @param $product_id
162
	 * @param $spbill_create_ip string 本地IP
163
	 * @param $ext array
164
	 * @return string
165
	 * @throws Exception
166
	 */
167
	public function getCodeUrl($body,$out_trade_no,$total_fee,$product_id,$spbill_create_ip = null,$ext = null){
168
		$data = ($ext && is_array($ext))?$ext:array();
169
		$data["body"]         = $body;
170
		$data["out_trade_no"] = $out_trade_no;
171
		$data["total_fee"]    = $total_fee;
172
		$data["spbill_create_ip"] = $spbill_create_ip?:$_SERVER["SERVER_ADDR"];
173
		$data["notify_url"]   = $this->config["notify_url"];
174
		$data["trade_type"]   = self::TRADETYPE_NATIVE;
175
		if(!$product_id) throw new Exception('product_id is required when trade_type is NATIVE');
176
		$data["product_id"]   = $product_id;
177
		$result = $this->unifiedOrder($data);
178
		return $result["code_url"];
179
	}
180
181
	/**
182
	 * H5支付获取支付跳转链接
183
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1
184
	 * @param $body string 商品描述
185
	 * @param $out_trade_no string 商户订单号
186
	 * @param $total_fee int 总金额(分)
187
	 * @param $ext array
188
	 * @return string
189
	 * @throws Exception
190
	 */
191
	public function getMwebUrl($body,$out_trade_no,$total_fee,$ext = null){
192
		$data = ($ext && is_array($ext))?$ext:array();
193
		$data["body"]         = $body;
194
		$data["out_trade_no"] = $out_trade_no;
195
		$data["total_fee"]    = $total_fee;
196
		$data["spbill_create_ip"] = isset($_SERVER["REMOTE_ADDR"])?$_SERVER["REMOTE_ADDR"]:'';
197
		$data["notify_url"]   = $this->config["notify_url"];
198
		$data["trade_type"]   = self::TRADETYPE_MWEB;
199
		if(!isset($this->config['h5_scene_info'])) throw new Exception('h5_scene_info should be configured');
200
		$data["scene_info"]   = json_encode($this->config['h5_scene_info']);
201
		$result = $this->unifiedOrder($data);
202
		return $result["mweb_url"];
203
	}
204
205
	/**
206
	 * 统一下单接口
207
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
208
	 * @param array $params
209
	 * @throws Exception
210
	 * @return string JSON
211
	 */
212
	public function unifiedOrder($params) {
213
		$data = array();
214
		$data["appid"] = $this->config["app_id"];
215
		$data["device_info"] = (isset($params['device_info'])&&trim($params['device_info'])!='')?$params['device_info']:null;
216
		$data["body"] = $params['body'];
217
		$data["detail"] = isset($params['detail'])?$params['detail']:null;//optional
218
		$data["attach"] = isset($params['attach'])?$params['attach']:null;//optional
219
		$data["out_trade_no"] = isset($params['out_trade_no'])?$params['out_trade_no']:null;
220
		$data["fee_type"] = isset($params['fee_type'])?$params['fee_type']:'CNY';
221
		$data["total_fee"]    = $params['total_fee'];
222
		$data["spbill_create_ip"] = $params['spbill_create_ip'];
223
		$data["time_start"] = isset($params['time_start'])?$params['time_start']:null;//optional
224
		$data["time_expire"] = isset($params['time_expire'])?$params['time_expire']:null;//optional
225
		$data["goods_tag"] = isset($params['goods_tag'])?$params['goods_tag']:null;
226
		$data["notify_url"] = $this->config["notify_url"];
227
		$data["trade_type"] = $params['trade_type'];
228
		if($params['trade_type'] == WechatPay::TRADETYPE_NATIVE){
229
			if(!isset($params['product_id'])) throw new Exception('product_id is required when trade_type is NATIVE');
230
			$data["product_id"] = $params['product_id'];
231
		}
232
		if($params['trade_type'] == WechatPay::TRADETYPE_JSAPI){
233
			if(!isset($params['openid'])) throw new Exception('openid is required when trade_type is JSAPI');
234
			$data["openid"] = $params['openid'];
235
		}
236
		$result = $this->post(self::URL_UNIFIEDORDER, $data);
237
		return $result;
238
	}
239
240
	/**
241
	 * 查询订单(根据微信订单号)
242
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
243
	 * @param $transaction_id string 微信订单号
244
	 * @return array
245
	 */
246
	public function queryOrderByTransactionId($transaction_id){
247
		$data = array();
248
		$data["appid"] = $this->config["app_id"];
249
		$data["transaction_id"] = $transaction_id;
250
		$result = $this->post(self::URL_ORDERQUERY, $data);
251
		return $result;
252
	}
253
254
	/**
255
	 * 查询订单(根据商户订单号)
256
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2
257
	 * @param $out_trade_no string 商户订单号
258
	 * @return array
259
	 */
260
	public function queryOrderByOutTradeNo($out_trade_no){
261
		$data = array();
262
		$data["appid"] = $this->config["app_id"];
263
		$data["out_trade_no"] = $out_trade_no;
264
		$result = $this->post(self::URL_ORDERQUERY, $data);
265
		return $result;
266
	}
267
268
	/**
269
	 * 查询退款(根据微信订单号)
270
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
271
	 * @param $transaction_id string 微信交易号
272
	 * @param $offset int 偏移
273
	 * @return array
274
	 */
275
	public function queryRefundByTransactionId($transaction_id,$offset = 0){
276
		$data = array();
277
		$data["appid"] = $this->config["app_id"];
278
		$data["transaction_id"] = $transaction_id;
279
		$data["offset"] = $offset;
280
		$result = $this->post(self::URL_REFUNDQUERY, $data);
281
		return $result;
282
	}
283
284
	/**
285
	 * 查询退款(根据商户订单号)
286
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
287
	 * @param $out_trade_no string 商户交易号
288
	 * @param $offset int 偏移
289
	 * @return array
290
	 */
291
	public function queryRefundByOutTradeNo($out_trade_no,$offset = 0){
292
		$data = array();
293
		$data["appid"] = $this->config["app_id"];
294
		$data["out_trade_no"] = $out_trade_no;
295
		$data["offset"] = $offset;
296
		$result = $this->post(self::URL_REFUNDQUERY, $data);
297
		return $result;
298
	}
299
300
	/**
301
	 * 查询退款(根据微信退款单号)
302
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
303
	 * @param $refund_id string 微信退款单号
304
	 * @param $offset int 偏移
305
	 * @return array
306
	 */
307
	public function queryRefundByRefundId($refund_id,$offset = 0){
308
		$data = array();
309
		$data["appid"] = $this->config["app_id"];
310
		$data["refund_id"] = $refund_id;
311
		$data["offset"] = $offset;
312
		$result = $this->post(self::URL_REFUNDQUERY, $data);
313
		return $result;
314
	}
315
316
	/**
317
	 * 查询退款(根据商户退款单号)
318
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
319
	 * @param $out_refund_no string 商户退款单号
320
	 * @param $offset int 偏移
321
	 * @return array
322
	 */
323
	public function queryRefundByOutRefundNo($out_refund_no,$offset = 0){
324
		$data = array();
325
		$data["appid"] = $this->config["app_id"];
326
		$data["out_refund_no"] = $out_refund_no;
327
		$data["offset"] = $offset;
328
		$result = $this->post(self::URL_REFUNDQUERY, $data);
329
		return $result;
330
	}
331
332
	/**
333
	 * 关闭订单
334
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
335
	 * @param $out_trade_no string 商户订单号
336
	 * @return array
337
	 */
338
	public function closeOrder($out_trade_no){
339
		$data = array();
340
		$data["appid"] = $this->config["app_id"];
341
		$data["out_trade_no"] = $out_trade_no;
342
		$result = $this->post(self::URL_CLOSEORDER, $data,false);
343
		return $result;
344
	}
345
346
	/**
347
	 * 申请退款 - 使用商户订单号
348
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4
349
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
350
	 * @param $out_trade_no string 商户订单号
351
	 * @param $out_refund_no string 商户退款单号
352
	 * @param $total_fee int 总金额(单位:分)
353
	 * @param $refund_fee int 退款金额(单位:分)
354
	 * @param $ext array 扩展数组
355
	 * @return array
356
	 */
357
	public function refundByOutTradeNo($out_trade_no,$out_refund_no,$total_fee,$refund_fee,$ext = array()){
358
		$data = ($ext && is_array($ext))?$ext:array();
359
		$data["appid"] = $this->config["app_id"];
360
		$data["out_trade_no"] = $out_trade_no;
361
		$data["out_refund_no"] = $out_refund_no;
362
		$data["total_fee"] = $total_fee;
363
		$data["refund_fee"] = $refund_fee;
364
		$result = $this->post(self::URL_REFUND, $data,true);
365
		return $result;
366
	}
367
368
	/**
369
	 * 申请退款 - 使用微信订单号
370
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4
371
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
372
	 * @param $transaction_id string 微信订单号
373
	 * @param $out_refund_no string 商户退款单号
374
	 * @param $total_fee int 总金额(单位:分)
375
	 * @param $refund_fee int 退款金额(单位:分)
376
	 * @param $ext array 扩展数组
377
	 * @return array
378
	 */
379
	public function refundByTransactionId($transaction_id,$out_refund_no,$total_fee,$refund_fee,$ext = array()){
380
		$data = ($ext && is_array($ext))?$ext:array();
381
		$data["appid"] = $this->config["app_id"];
382
		$data["transaction_id"] = $transaction_id;
383
		$data["out_refund_no"] = $out_refund_no;
384
		$data["total_fee"] = $total_fee;
385
		$data["refund_fee"] = $refund_fee;
386
		$result = $this->post(self::URL_REFUND, $data,true);
387
		return $result;
388
	}
389
390
	/**
391
	 * 撤销订单 - 使用商户订单号
392
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
393
	 * @param $out_trade_no string 商户订单号
394
	 * @return array
395
	 */
396
	public function reverseByOutTradeNo($out_trade_no){
397
		$data = array();
398
		$data["appid"] = $this->config["app_id"];
399
		$data["out_trade_no"] = $out_trade_no;
400
		$result = $this->post(self::URL_REVERSE, $data,true);
401
		return $result;
402
	}
403
404
	/**
405
	 * 撤销订单 - 使用微信订单号
406
	 * @ref  https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
407
	 * @param $transaction_id string 微信订单号
408
	 * @return array
409
	 */
410
	public function reverseByTransactionId($transaction_id){
411
		$data = array();
412
		$data["appid"] = $this->config["app_id"];
413
		$data["transaction_id"] = $transaction_id;
414
		$result = $this->post(self::URL_REVERSE, $data,true);
415
		return $result;
416
	}
417
418
	/**
419
	 * 下载对账单
420
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_6
421
	 * @param $bill_date string 下载对账单的日期,格式:20140603
422
	 * @param $bill_type string 类型 ALL|SUCCESS
423
	 * @return array
424
	 */
425
	public function downloadBill($bill_date,$bill_type = 'ALL'){
426
		$data = array();
427
		$data["appid"] = $this->config["app_id"];
428
		$data["bill_date"] = $bill_date;
429
		$data["bill_type"] = $bill_type;
430
		$result = $this->post(self::URL_DOWNLOADBILL, $data);
431
		return $result;
432
	}
433
434
	/**
435
	 * 下载资金账单
436
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_18&index=7
437
	 * @param $bill_date string 资金账单日期,格式:20140603
438
	 * @param $account_type string 资金账户类型 Basic|Operation|Fees
439
	 * @param $tar_type string 压缩账单
440
	 * @return array
441
	 */
442
	public function downloadFundFlow($bill_date,$account_type = self::ACCOUNTTYPE_BASIC,$tar_type = 'GZIP'){
443
		$data = array();
444
		$data["appid"] = $this->config["app_id"];
445
		$data["bill_date"] = $bill_date;
446
		$data["account_type"] = $account_type;
447
		$data["tar_type"] = $tar_type;
448
		$result = $this->post(self::URL_DOWNLOAD_FUND_FLOW, $data);
449
		return $result;
450
	}
451
452
	/**
453
	 * 发放普通红包
454
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
455
	 * @param $mch_billno string 商户订单号
456
	 * @param $send_name string 商户名称
457
	 * @param $re_openid string 用户openid
458
	 * @param $total_amount int 付款金额 单位分
459
	 * @param $total_num int 红包发放总人数
460
	 * @param $wishing string 红包祝福语
461
	 * @param $act_name string 活动名称
462
	 * @param $remark string 备注
463
	 * @param $scene_id string 场景id,发放红包使用场景,红包金额大于200时必传 PRODUCT_1:商品促销 PRODUCT_2:抽奖 PRODUCT_3:虚拟物品兑奖 PRODUCT_4:企业内部福利 PRODUCT_5:渠道分润 PRODUCT_6:保险回馈 PRODUCT_7:彩票派奖 PRODUCT_8:税务刮奖
464
	 * @param $riskinfo string 活动信息
465
	 * @param $consume_mch_id string 资金授权商户号
466
	 * @return array
467
	 * @throws Exception
468
	 */
469
	public function sendRedPack($mch_billno,$send_name,$re_openid,$total_amount,$total_num,$wishing,$act_name,$remark,$scene_id = '',$riskinfo = '',$consume_mch_id = ''){
470
		$data = array();
471
		$data["wxappid"] = $this->config["app_id"];
472
		$data["mch_billno"] = $mch_billno;
473
		$data["send_name"] = $send_name;
474
		$data["re_openid"] = $re_openid;
475
		$data["total_amount"] = $total_amount;
476
		if($total_amount > 20000 && trim($scene_id)=='') throw new Exception("scene_id is required when total_amount beyond 20000");
477
		$data["total_num"] = $total_num;
478
		$data["wishing"] = $wishing;
479
		$data["act_name"] = $act_name;
480
		$data["remark"] = $remark;
481
		$data["scene_id"] = $scene_id;
482
		$data["riskinfo"] = $riskinfo;
483
		$data["consume_mch_id"] = $consume_mch_id;
484
		$result = $this->post(self::URL_SENDREDPACK, $data, true); //cert is required
485
		return $result;
486
	}
487
488
	/**
489
	 * 发放裂变红包
490
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
491
	 * @param $mch_billno string 商户订单号
492
	 * @param $send_name string 商户名称
493
	 * @param $re_openid string 用户openid
494
	 * @param $total_amount int 付款金额 单位分
495
	 * @param $total_num int 红包发放总人数
496
	 * @param $wishing string 红包祝福语
497
	 * @param $act_name string 活动名称
498
	 * @param $remark string 备注
499
	 * @param $scene_id string 场景id,发放红包使用场景,红包金额大于200时必传 PRODUCT_1:商品促销 PRODUCT_2:抽奖 PRODUCT_3:虚拟物品兑奖 PRODUCT_4:企业内部福利 PRODUCT_5:渠道分润 PRODUCT_6:保险回馈 PRODUCT_7:彩票派奖 PRODUCT_8:税务刮奖
500
	 * @param $riskinfo string 活动信息
501
	 * @param $consume_mch_id string 资金授权商户号
502
	 * @return array
503
	 * @throws Exception
504
	 */
505
	public function sendGroupRedPack($mch_billno,$send_name,$re_openid,$total_amount,$total_num,$wishing,$act_name,$remark,$scene_id = '',$riskinfo = '',$consume_mch_id = ''){
506
		$data = array();
507
		$data["wxappid"] = $this->config["app_id"];//NOTE: WXappid
508
		$data["mch_billno"] = $mch_billno;
509
		$data["send_name"] = $send_name;
510
		$data["re_openid"] = $re_openid;
511
		$data["total_amount"] = $total_amount;
512
		if($total_amount > 20000 && trim($scene_id)=='') throw new Exception("scene_id is required when total_amount beyond 20000(200rmb)");
513
		$data["total_num"] = $total_num;
514
		$data["amt_type"] = 'ALL_RAND'; //红包金额设置方式 ALL_RAND—全部随机
515
		$data["wishing"] = $wishing;
516
		$data["act_name"] = $act_name;
517
		$data["remark"] = $remark;
518
		$data["scene_id"] = $scene_id;
519
		$data["riskinfo"] = $riskinfo;
520
		$data["consume_mch_id"] = $consume_mch_id;
521
		$result = $this->post(self::URL_SENDGROUPREDPACK, $data, true); //cert is required
522
		return $result;
523
	}
524
525
	/**
526
	 * 查询红包记录
527
	 * @param $mch_billno string 商户订单号
528
	 * @return array
529
	 * @throws Exception
530
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_6&index=5
531
	 */
532
	public function getHbInfo($mch_billno){
533
		$data = array();
534
		$data["mch_billno"] = $mch_billno;
535
		$data["appid"] = $this->config["app_id"];
536
		$data["bill_type"] = 'MCHT'; //MCHT:通过商户订单号获取红包信息。
537
		$result = $this->post(self::URL_GETHBINFO, $data, true); //cert is required
538
		return $result;
539
	}
540
541
	/**
542
	 * 拉取订单评价数据
543
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
544
	 * @param string $begin_time 开始时间,格式为yyyyMMddHHmmss
545
	 * @param string $end_time 结束时间,格式为yyyyMMddHHmmss
546
	 * @param int $offset 偏移
547
	 * @param int $limit 条数
548
	 * @return array
549
	 */
550
	public function batchQueryComment($begin_time,$end_time,$offset = 0,$limit = 200){
551
		$data = array();
552
		$data["appid"] = $this->config["app_id"];
553
		$data["begin_time"] = $begin_time;
554
		$data["end_time"] = $end_time;
555
		$data["offset"] = $offset;
556
		$data["limit"] = $limit;
557
		$data["sign"] = $this->sign($data,WechatPay::SIGNTYPE_HMACSHA256);
558
		$result = $this->post(self::URL_BATCHQUERYCOMMENT, $data, true); //cert is required
559
		return $result;
560
	}
561
562
	/**
563
	 * 获取支付参数(JSAPI - 公众号/小程序支付 , APP - APP支付)
564
	 * @param $prepay_id string 预支付ID
565
	 * @param $trade_type string 支付类型
566
	 * @return array
567
	 */
568
	public function getPackage($prepay_id, $trade_type = WechatPay::TRADETYPE_JSAPI) {
569
		$data = array();
570
		if ($trade_type == WechatPay::TRADETYPE_JSAPI){
571
			$data["package"]   = "prepay_id=$prepay_id";
572
			$data["timeStamp"] = time();
573
			$data["nonceStr"]  = $this->getNonceStr();
574
			$data["appId"] = $this->config["app_id"];
575
			$data["signType"]  = "MD5";
576
			$data["paySign"]   = $this->sign($data);
577
		} else if ($trade_type == WechatPay::TRADETYPE_APP){
578
			$data["package"]   = "Sign=WXPay";
579
			$data['prepayid'] = $prepay_id;
580
			$data['partnerid'] = $this->config["mch_id"];
581
			$data["timestamp"] = time();
582
			$data["noncestr"]  = $this->getNonceStr();
583
			$data["appid"] = $this->config["app_id"];
584
			$data["sign"]   = $this->sign($data);
585
		}
586
		return $data;
587
	}
588
589
	/**
590
	 * 提交刷卡支付
591
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
592
	 * @param $body
593
	 * @param $out_trade_no
594
	 * @param $total_fee
595
	 * @param $spbill_create_ip
596
	 * @param $auth_code
597
	 * @param array $ext
598
	 * @return array
599
	 */
600
	public function microPay($body,$out_trade_no,$total_fee,$spbill_create_ip,$auth_code,$ext = array()){
601
		$data = (!empty($ext) && is_array($ext))?$ext:array();
602
		$data["appid"] = $this->config["app_id"];
603
		$data["body"]         = $body;
604
		$data["out_trade_no"] = $out_trade_no;
605
		$data["total_fee"]    = $total_fee;
606
		$data["spbill_create_ip"] = $spbill_create_ip;
607
		$data["auth_code"] = $auth_code;
608
		$result = $this->post(self::URL_MICROPAY,$data,false);
609
		return $result;
610
	}
611
612
	/**
613
	 * 支付结果通知处理
614
	 * @param $notify_data array|string 通知数据
615
	 * @param $callback callable 回调
616
	 * @return null
617
	 * @throws Exception
618
	 */
619
	public function onPaidNotify($notify_data,callable $callback = null){
620
		if(!is_array($notify_data)){
621
			$notify_data = $this->xml2array($notify_data);
622
		}
623
		if($this->validateSign($notify_data)){
624
			if($callback && is_callable($callback)){
625
				return call_user_func_array( $callback , [$notify_data] );
626
			}else{
627
				$this->responseNotify();
628
			}
629
		}else{
630
			throw new Exception('Invalid paid notify data');
631
		}
632
	}
633
634
	/**
635
	 * 退款结果通知处理
636
	 * @param string|array $notify_data 通知数据(XML/array)
637
	 * @param callable $callback 回调
638
	 * @return mixed
639
	 * @throws Exception
640
	 */
641
	public function onRefundedNotify($notify_data,callable $callback = null){
642
		if(!is_array($notify_data)){
643
			$notify_data = $this->xml2array($notify_data);
644
		}
645
		if($this->validateSign($notify_data)){
646
			if($callback && is_callable($callback)){
647
				return call_user_func_array( $callback , $notify_data );
648
			}else{
649
				$this->responseNotify();
650
			}
651
		}else{
652
			throw new Exception('Invalid refunded notify data');
653
		}
654
	}
655
656
	/**
657
	 * 验证数据签名
658
	 * @param $data array 数据数组
659
	 * @return boolean 数据校验结果
660
	 */
661
	public function validateSign($data) {
662
		if (!isset($data["sign"])) {
663
			return false;
664
		}
665
		$sign = $data["sign"];
666
		unset($data["sign"]);
667
		return $this->sign($data) == $sign;
668
	}
669
670
	/**
671
	 * 响应微信支付后台通知
672
	 * @param $return_code string 返回状态码 SUCCESS/FAIL
673
	 * @param $return_msg string 返回信息
674
	 */
675
	public function responseNotify($return_code="SUCCESS", $return_msg= 'OK') {
676
		$data = array();
677
		$data["return_code"] = $return_code;
678
		if ($return_msg) {
679
			$data["return_msg"] = $return_msg;
680
		}
681
		$xml = $this->array2xml($data);
682
		print $xml;
683
	}
684
685
	/**
686
	 * 交易保障
687
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_8&index=8
688
	 * @param string $interface_url
689
	 * @param string $execution_time
690
	 * @param string $return_code
691
	 * @param string $result_code
692
	 * @param string $user_ip
693
	 * @param string $out_trade_no
694
	 * @param string $time
695
	 * @param string $device_info
696
	 * @param string $return_msg
697
	 * @param string $err_code
698
	 * @param string $err_code_des
699
	 * @return array
700
	 */
701
	public function report($interface_url,$execution_time,$return_code,$result_code,$user_ip,$out_trade_no = null,$time = null,$device_info = null,
702
	                       $return_msg = null,$err_code = null,$err_code_des = null){
703
		$data = array();
704
		$data["appid"] = $this->config["app_id"];
705
		$data["interface_url"] = $interface_url;
706
		$data["execution_time"] = $execution_time;
707
		$data["return_code"] = $return_code;
708
		$data["result_code"] = $result_code;
709
		$data["user_ip"] = $user_ip;
710
		if($out_trade_no) $data["out_trade_no"] = $out_trade_no;
711
		if($time) $data["time"] = $time;
712
		if($device_info) $data["device_info"] = $device_info;
713
		if($return_msg) $data["return_msg"] = $return_msg;
714
		if($err_code) $data["err_code"] = $err_code;
715
		if($err_code_des) $data["err_code_des"] = $err_code_des;
716
		$result = $this->post(self::URL_REPORT, $data, false);
717
		return $result;
718
	}
719
720
	/**
721
	 * 转换短链接
722
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8
723
	 * @param $longurl
724
	 * @return string
725
	 */
726
	public function shortUrl($longurl){
727
		$data = array();
728
		$data["appid"] = $this->config["app_id"];
729
		$data["long_url"] = $longurl;
730
		$result = $this->post(self::URL_SHORTURL,$data,false);
731
		return $result['short_url'];
732
	}
733
734
	/**
735
	 * 授权码查询openid
736
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=10
737
	 * @param $auth_code
738
	 * @return mixed
739
	 */
740
	public function authCodeToOpenId($auth_code){
741
		$data = array();
742
		$data["appid"] = $this->config["app_id"];
743
		$data["auth_code"] = $auth_code;
744
		$result = $this->post(self::URL_AUTHCODETOOPENID,$data,false);
745
		return $result['openid'];
746
	}
747
748
	/**
749
	 * 企业付款到零钱
750
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
751
	 * @param $partner_trade_no
752
	 * @param $openid
753
	 * @param $amount
754
	 * @param $desc
755
	 * @param $spbill_create_ip
756
	 * @param $check_name
757
	 * @param $re_user_name
758
	 * @return array
759
	 * @throws Exception
760
	 */
761
	public function transferWallet($partner_trade_no,$openid,$amount,$desc,$spbill_create_ip = null,$re_user_name = null,$check_name = WechatPay::CHECKNAME_FORCECHECK){
762
		$data = array();
763
		if($check_name == WechatPay::CHECKNAME_FORCECHECK && !$re_user_name) throw new Exception('Real name is required');
764
		$data["mch_appid"] = $this->config["app_id"];
765
		$data["mchid"] = $this->config["mch_id"];
766
		$data["partner_trade_no"] = $partner_trade_no;
767
		$data["openid"] = $openid;
768
		$data["amount"] = $amount;
769
		$data["desc"] = $desc;
770
		$data['spbill_create_ip'] = $spbill_create_ip?:$_SERVER['SERVER_ADDR'];
771
		$data["check_name"] = $check_name;
772
		$data["re_user_name"] = $re_user_name;
773
		$result = $this->post(self::URL_TRANSFER_WALLET,$data,true);
774
		return $result;
775
	}
776
777
	/**
778
	 * 查询企业付款
779
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
780
	 * @param $partner_trade_no
781
	 * @return array
782
	 */
783
	public function queryTransferWallet($partner_trade_no){
784
		$data = array();
785
		$data["appid"] = $this->config["app_id"];
786
		$data["mch_id"] = $this->config["mch_id"];
787
		$data["partner_trade_no"] = $partner_trade_no;
788
		$result = $this->post(self::URL_QUERY_TRANSFER_WALLET,$data,true);
789
		return $result;
790
	}
791
792
	/**
793
	 * 企业付款到银行卡
794
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
795
	 * @param $partner_trade_no
796
	 * @param $bank_no
797
	 * @param $true_name
798
	 * @param $bank_code
799
	 * @param $amount
800
	 * @param $desc
801
	 * @return array
802
	 * @throws Exception
803
	 */
804
	public function transferBankCard($partner_trade_no,$bank_no,$true_name,$bank_code,$amount,$desc){
805
		if(!in_array($bank_code,array_values(self::$BANKCODE))) throw new Exception("Unsupported bank code: $bank_code");
806
		$data = array();
807
		$data["partner_trade_no"] = $partner_trade_no;
808
		$enc_bank_no = $this->rsaEncrypt($bank_no);
809
		$data["enc_bank_no"] = $enc_bank_no;
810
		$enc_true_name = $this->rsaEncrypt($true_name);
811
		$data["enc_true_name"] = $enc_true_name;
812
		$data["bank_code"] = $bank_code;
813
		$data["desc"] = $desc;
814
		$data["amount"] = $amount;
815
		$result = $this->post(self::URL_TRANSFER_BANKCARD,$data,true);
816
		return $result;
817
	}
818
819
	/**
820
	 * 查询企业付款银行卡
821
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3
822
	 * @param $partner_trade_no
823
	 * @return array
824
	 */
825
	public function queryTransferBankCard($partner_trade_no){
826
		$data = array();
827
		$data["appid"] = $this->config["app_id"];
828
		$data["mch_id"] = $this->config["mch_id"];
829
		$data["partner_trade_no"] = $partner_trade_no;
830
		$result = $this->post(self::URL_QUERY_TRANSFER_WALLET,$data,true);
831
		return $result;
832
	}
833
834
	/**
835
	 * 发放代金券
836
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_3&index=4
837
	 * @param $coupon_stock_id
838
	 * @param $open_id
839
	 * @param $partner_trade_no
840
	 * @param string $op_user_id
841
	 * @param array $ext
842
	 * @return array
843
	 */
844
	public function sendCoupon($coupon_stock_id,$open_id,$partner_trade_no,$op_user_id = '',$ext = array()){
845
		$data = (!empty($ext) && is_array($ext))?$ext:array();
846
		$data["partner_trade_no"] = $partner_trade_no;
847
		$data["coupon_stock_id"] = $coupon_stock_id;
848
		$data["openid_count"] = 1;
849
		$data["open_id"] = $open_id;
850
		$data["op_user_id"] = $op_user_id;
851
		$result = $this->post(self::URL_SEND_COUPON,$data,true);
852
		return $result;
853
	}
854
855
	/**
856
	 * 查询代金券批次
857
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_4&index=5
858
	 * @param $coupon_stock_id
859
	 * @param string $op_user_id
860
	 * @return array
861
	 */
862
	public function queryCouponStock($coupon_stock_id,$op_user_id = ''){
863
		$data = array();
864
		$data["coupon_stock_id"] = $coupon_stock_id;
865
		$data["op_user_id"] = $op_user_id;
866
		$result = $this->post(self::URL_QUERY_COUPON_STOCK,$data,false);
867
		return $result;
868
	}
869
870
	/**
871
	 * 查询代金券信息
872
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_5&index=6
873
	 * @param $coupon_id
874
	 * @param $open_id
875
	 * @param $stock_id
876
	 * @param string $op_user_id
877
	 * @param array $ext
878
	 * @return array
879
	 */
880
	public function queryCouponsInfo($coupon_id,$open_id,$stock_id,$op_user_id = '',$ext = array()){
881
		$data = (!empty($ext) && is_array($ext))?$ext:array();
882
		$data["coupon_id"] = $coupon_id;
883
		$data["stock_id"] = $stock_id;
884
		$data["open_id"] = $open_id;
885
		$data["op_user_id"] = $op_user_id;
886
		$result = $this->post(self::URL_QUERY_COUPON_INFO,$data,false);
887
		return $result;
888
	}
889
890
	/**
891
	 * 获取RSA加密公钥
892
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
893
	 * @param bool $refresh
894
	 * @return string
895
	 * @throws Exception
896
	 */
897
	public function getPublicKey($refresh = false){
898
		if (!$refresh && file_exists($this->config["rsa_pubkey_path"])) {
899
			$pubkey = file_get_contents($this->config["rsa_pubkey_path"]);
900
			return $pubkey;
901
		}
902
		$data = array();
903
		$data["mch_id"] = $this->config["mch_id"];
904
		$data["sign_type"] = $this->config["sign_type"];
905
		$result = $this->post(self::URL_GETPUBLICKEY,$data,true);
906
		$pubkey = $result['pub_key'];
907
		$pubkey = $this->convertPKCS1toPKCS8($pubkey);
908
		$fp = fopen($this->config["rsa_pubkey_path"], "w");
909
		if ($fp) {
0 ignored issues
show
introduced by
$fp is of type resource|false, thus it always evaluated to false.
Loading history...
910
			fwrite($fp, $pubkey);
911
			fclose($fp);
912
			return $pubkey;
913
		}else {
914
			throw new Exception("RSA public key not found");
915
		}
916
	}
917
918
	private function convertPKCS1toPKCS8($pkcs1){
919
		$start_key = $pkcs1;
920
		$start_key = str_replace('-----BEGIN RSA PUBLIC KEY-----', '', $start_key);
921
		$start_key = trim(str_replace('-----END RSA PUBLIC KEY-----', '', $start_key));
922
		$key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' . str_replace("\n", '', $start_key);
923
		$key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
924
		return $key;
925
	}
926
927
	public function rsaEncrypt($data){
928
		$pubkey = $this->getPublicKey();
929
		$encrypted = null;
930
		$pubkey = openssl_get_publickey($pubkey);
931
		if (openssl_public_encrypt($data, $encrypted, $pubkey,OPENSSL_PKCS1_OAEP_PADDING))
932
			$data = base64_encode($encrypted);
933
		else
934
			throw new Exception('Unable to encrypt data');
935
		return $data;
936
	}
937
938
	/**
939
	 * sandbox环境获取验签秘钥
940
	 * @ref https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=23_1
941
	 * @return array
942
	 */
943
	public function getSignKey(){
944
		$data = array();
945
		$data["mch_id"] = $this->config["mch_id"];
946
		$result = $this->post($this->getSignKeyUrl,$data,false);
947
		return $result['sandbox_signkey'];
948
	}
949
950
	/**
951
	 * 获取JSAPI所需要的页面参数
952
	 * @param string $url
953
	 * @param string $ticket
954
	 * @return array
955
	 */
956
	public function getSignPackage($url, $ticket = null){
957
		if(!$ticket) $ticket = $this->getTicket();
958
		$timestamp = time();
959
		$nonceStr = $this->getNonceStr();
960
		$rawString = "jsapi_ticket=$ticket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
961
		$signature = sha1($rawString);
962
963
		$signPackage = array(
964
			"appId" => $this->config['app_id'],
965
			"nonceStr" => $nonceStr,
966
			"timestamp" => $timestamp,
967
			"url" => $url,
968
			"signature" => $signature,
969
			"rawString" => $rawString
970
		);
971
		return $signPackage;
972
	}
973
974
	/**
975
	 * 获取JSAPI Ticket
976
	 * @param boolean $cache
977
	 * @return string
978
	 */
979
	public function getTicket($cache = true){
980
		$ticket = null;
981
		if(isset($this->config['jsapi_ticket']) && file_exists($this->config['jsapi_ticket'])){
982
			$data = json_decode(file_get_contents($this->config['jsapi_ticket']));
983
			if ($data && $data->expires_at < time()) {
984
				$ticket = $data->ticket;
985
			}
986
		}
987
		if(!$ticket){
988
			$data = $this->getWechatOAuth()->getTicket();
989
			$data = json_decode($data);
990
			$data->expires_at = time() + $data->expires_in;
991
			if($cache === true){
992
				$fp = fopen($this->config["jsapi_ticket"], "w");
993
				fwrite($fp, json_encode($data));
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

993
				fwrite(/** @scrutinizer ignore-type */ $fp, json_encode($data));
Loading history...
994
				if ($fp) fclose($fp);
0 ignored issues
show
introduced by
$fp is of type resource|false, thus it always evaluated to false.
Loading history...
995
			}
996
			$ticket = $data->ticket;
997
		}
998
		return $ticket;
999
	}
1000
1001
	private function post($url, $data,$cert = true) {
1002
		if(!isset($data['mch_id']) && !isset($data['mchid'])) $data["mch_id"] = $this->config["mch_id"];
1003
		if(!isset($data['nonce_str'])) $data["nonce_str"] = $this->getNonceStr();
1004
		if(!isset($data['sign'])) $data['sign'] = $this->sign($data);
1005
		$this->requestXML = $this->responseXML = null;
1006
		$this->requestArray = $this->responseArray = null;
1007
1008
		$this->requestArray = $data;
1009
		$this->requestXML = $this->array2xml($data);
1010
		$opts = [
1011
			CURLOPT_SSL_VERIFYPEER => false,
1012
			CURLOPT_SSL_VERIFYHOST => false,
1013
			CURLOPT_RETURNTRANSFER => true,
1014
			CURLOPT_TIMEOUT => 10
1015
		];
1016
		if($cert == true){
1017
			$opts[CURLOPT_SSLCERTTYPE] = 'PEM';
1018
			$opts[CURLOPT_SSLCERT] = $this->config['ssl_cert_path'];
1019
			$opts[CURLOPT_SSLKEYTYPE] = 'PEM';
1020
			$opts[CURLOPT_SSLKEY] = $this->config['ssl_key_path'];
1021
		}
1022
		$processResponse = true;
1023
		if(in_array($url,[self::URL_DOWNLOADBILL,self::URL_DOWNLOAD_FUND_FLOW,self::URL_BATCHQUERYCOMMENT])){
1024
			$processResponse = false;
1025
		}
1026
		if($this->sandbox === true){
1027
			$host = "https://api.mch.weixin.qq.com";
1028
			$url = str_replace($host,'',$url);
1029
			$url = "{$host}/sandboxnew{$url}";
1030
		}
1031
		$content = $this->httpClient->post($url,$this->requestXML,[],$opts);
1032
		if(!$content) throw new Exception("Empty response with {$this->requestXML}");
1033
1034
		$this->responseXML = $content;
1035
		if($processResponse)
1036
			return $this->processResponseXML($this->responseXML);
1037
		else return $this->responseXML;
1038
1039
	}
1040
1041
	private function processResponseXML($responseXML){
1042
		$result = $this->xml2array($responseXML);
1043
		$this->responseArray = $result;
1044
		if(empty($result['return_code'])){
1045
			throw new Exception("No return code presents in {$this->responseXML}");
1046
		}
1047
		$this->returnCode = $result["return_code"];
1048
		$this->returnMsg = isset($result['return_msg'])?$result['return_msg']:'';
1049
1050
		if ($this->returnCode == "SUCCESS") {
1051
			if(isset($result['result_code']) && $result['result_code'] == "FAIL"){
1052
				$this->resultCode = $result['result_code'];
1053
				$this->errCode = $result['err_code'];
1054
				$this->errCodeDes = $result['err_code_des'];
1055
				throw new Exception("[$this->errCode]$this->errCodeDes");
1056
			}else{
1057
				return $result;
1058
			}
1059
		} else {
1060
			if($result["return_code"] == "FAIL"){
1061
				throw new Exception($this->returnMsg);
1062
			}else{
1063
				$this->resultCode = $result['result_code'];
1064
				$this->errCode = $result['err_code'];
1065
				$this->errCodeDes = $result['err_code_des'];
1066
				throw new Exception("[$this->errCode]$this->errCodeDes");
1067
			}
1068
		}
1069
	}
1070
1071
	public function sign($data,$sign_type = WechatPay::SIGNTYPE_MD5) {
1072
		ksort($data);
1073
		$string1 = "";
1074
		foreach ($data as $k => $v) {
1075
			if ($v && trim($v)!='') {
1076
				$string1 .= "$k=$v&";
1077
			}
1078
		}
1079
		$stringSignTemp = $string1 . "key=" . $this->config["api_key"];
1080
		if($sign_type == WechatPay::SIGNTYPE_MD5){
1081
			$sign = strtoupper(md5($stringSignTemp));
1082
		}elseif($sign_type == WechatPay::SIGNTYPE_HMACSHA256){
1083
			$sign = strtoupper(hash_hmac('sha256',$stringSignTemp,$this->config["api_key"]));
1084
		}else throw new Exception("Not supported sign type - $sign_type");
1085
		return $sign;
1086
	}
1087
1088
	private function array2xml($array) {
1089
		$xml = "<xml>" . PHP_EOL;
1090
		foreach ($array as $k => $v) {
1091
			if($v && trim($v)!='')
1092
				$xml .= "<$k><![CDATA[$v]]></$k>" . PHP_EOL;
1093
		}
1094
		$xml .= "</xml>";
1095
		return $xml;
1096
	}
1097
1098
	private function xml2array($xml) {
1099
		$array = array();
1100
		$tmp = array();
0 ignored issues
show
Unused Code introduced by
The assignment to $tmp is dead and can be removed.
Loading history...
1101
		try{
1102
			$tmp = (array) simplexml_load_string($xml);
1103
		}catch(Exception $e){
1104
			throw $e;
1105
		}
1106
		foreach ( $tmp as $k => $v) {
1107
			$array[$k] = (string) $v;
1108
		}
1109
		return $array;
1110
	}
1111
1112
	private function getNonceStr() {
1113
		return substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"),0,32);
1114
	}
1115
1116
}