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

WechatPay::getConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
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
}