WxPay.MicroPay.php
4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
/**
*
* example目录下为简单的支付样例,仅能用于搭建快速体验微信支付使用
* 样例的作用仅限于指导如何使用sdk,在安全上面仅做了简单处理, 复制使用样例代码时请慎重
* 请勿直接直接使用样例对外提供服务
*
**/
require_once "../lib/WxPay.Api.php";
require_once "WxPay.Config.php";
/**
*
* 刷卡支付实现类
* 该类实现了一个刷卡支付的流程,流程如下:
* 1、提交刷卡支付
* 2、根据返回结果决定是否需要查询订单,如果查询之后订单还未变则需要返回查询(一般反复查10次)
* 3、如果反复查询10订单依然不变,则发起撤销订单
* 4、撤销订单需要循环撤销,一直撤销成功为止(注意循环次数,建议10次)
*
* 该类是微信支付提供的样例程序,商户可根据自己的需求修改,或者使用lib中的api自行开发,为了防止
* 查询时hold住后台php进程,商户查询和撤销逻辑可在前端调用
*
* @author widy
*
*/
class MicroPay
{
/**
*
* 提交刷卡支付,并且确认结果,接口比较慢
* @param WxPayMicroPay $microPayInput
* @throws WxpayException
* @return 返回查询接口的结果
*/
public function pay($microPayInput)
{
//①、提交被扫支付
$config = new WxPayConfig();
$result = WxPayApi::micropay($config, $microPayInput, 5);
//如果返回成功
if(!array_key_exists("return_code", $result)
|| !array_key_exists("result_code", $result))
{
echo "接口调用失败,请确认是否输入是否有误!";
throw new WxPayException("接口调用失败!");
}
//取订单号
$out_trade_no = $microPayInput->GetOut_trade_no();
//②、接口调用成功,明确返回调用失败
if($result["return_code"] == "SUCCESS" &&
$result["result_code"] == "FAIL" &&
$result["err_code"] != "USERPAYING" &&
$result["err_code"] != "SYSTEMERROR")
{
return false;
}
//③、确认支付是否成功
$queryTimes = 10;
while($queryTimes > 0)
{
$succResult = 0;
$queryResult = $this->query($out_trade_no, $succResult);
//如果需要等待1s后继续
if($succResult == 2){
sleep(2);
continue;
} else if($succResult == 1){//查询成功
return $queryResult;
} else {//订单交易失败
break;
}
}
//④、次确认失败,则撤销订单
if(!$this->cancel($out_trade_no))
{
throw new WxpayException("撤销单失败!");
}
return false;
}
/**
*
* 查询订单情况
* @param string $out_trade_no 商户订单号
* @param int $succCode 查询订单结果
* @return 0 订单不成功,1表示订单成功,2表示继续等待
*/
public function query($out_trade_no, &$succCode)
{
$queryOrderInput = new WxPayOrderQuery();
$queryOrderInput->SetOut_trade_no($out_trade_no);
$config = new WxPayConfig();
try{
$result = WxPayApi::orderQuery($config, $queryOrderInput);
} catch(Exception $e) {
Log::ERROR(json_encode($e));
}
if($result["return_code"] == "SUCCESS"
&& $result["result_code"] == "SUCCESS")
{
//支付成功
if($result["trade_state"] == "SUCCESS"){
$succCode = 1;
return $result;
}
//用户支付中
else if($result["trade_state"] == "USERPAYING"){
$succCode = 2;
return false;
}
}
//如果返回错误码为“此交易订单号不存在”则直接认定失败
if($result["err_code"] == "ORDERNOTEXIST")
{
$succCode = 0;
} else{
//如果是系统错误,则后续继续
$succCode = 2;
}
return false;
}
/**
*
* 撤销订单,如果失败会重复调用10次
* @param string $out_trade_no
* @param 调用深度 $depth
*/
public function cancel($out_trade_no, $depth = 0)
{
try {
if($depth > 10){
return false;
}
$clostOrder = new WxPayReverse();
$clostOrder->SetOut_trade_no($out_trade_no);
$config = new WxPayConfig();
$result = WxPayApi::reverse($config, $clostOrder);
//接口调用失败
if($result["return_code"] != "SUCCESS"){
return false;
}
//如果结果为success且不需要重新调用撤销,则表示撤销成功
if($result["result_code"] != "SUCCESS"
&& $result["recall"] == "N"){
return true;
} else if($result["recall"] == "Y") {
return $this->cancel($out_trade_no, ++$depth);
}
} catch(Exception $e) {
Log::ERROR(json_encode($e));
}
return false;
}
}