PHP后台支付的開發:微信支付和支付寶支付
關於支付的流程之類的就不做解釋,大家可以自行搜索!
- 微信支付
項目前提:本人用的是tp框架,PHP語言
下載到微信平台提供的微信支付接口文件,放在了tp第三方類庫vendor,命名為WxpayAPI,

1
2
3
4
5
6
|
WxpayAPI/lib/WxPay.Api.php 接口訪問類;
WxpayAPI/lib/WxPay.Config.php 配置賬號信息;
WxpayAPI/lib/WxPay.Data.php 數據對象基礎類;
WxpayAPI/lib/WxPay.Exception.php 微信支付API異常類;
WxpayAPI/lib/WxPay.Notify.php 回調基礎類
WxpayAPI/example/WxPay.JsApiPay.php JSAPI支付實現類
|

1.對源碼進行了部分修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
(1)WxPay.Api.php 里注釋掉
//require_once "WxPay.Exception.php";
//require_once "WxPay.Config.php";
//require_once "WxPay.Data.php";
(2)WxPay.Config.php里
需要根據商戶信息對APPID , MCHID ,KEY , APPSECRET 進行配置。
(3)WxPay.Data.php 里注釋掉
//require_once "WxPay.Config.php";
//require_once "WxPay.Exception.php";
(4)WxPay.JsApiPay.php 里注釋掉
//require_once "../lib/WxPay.Api.php";
|
配置好這些,接下來就是我們的重點部分了。
2.在訂單控制器GoodsController.class.php有訂單函數sure()和回調信息函數 Callback_url()
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
|
/**
* 提交訂單函數
*/
public
function
sure() {
$o_model
= D(
"Wine/Orders"
);
if
(IS_AJAX) {
$data
= I(
"post."
);
if
(
$o_model
->create(
$data
)) {
if
(!sp_check_verify_code()) {
$this
->error(
"驗證碼錯誤!"
);
}
#生成隨機訂單號
$order_code
=
'O'
.
date
(
'YmdHis'
) .
$o_model
->get_order_code(4);
while
(
$o_model
->findone(
array
(
"order_code"
=>
$order_code
))) {
$order_code
=
'O'
.
date
(
'YmdHis'
) .
$o_model
->get_order_code(4);
}
$data
[
'order_code'
] =
$order_code
;
$addr
[0] =
$_POST
[
'prov'
];
$addr
[1] =
$_POST
[
'city'
];
$addr
[2] =
$_POST
[
'dist'
];
$addr
[3] =
$_POST
[
'area'
];
$data
[
'area'
] = serialize(
$addr
);
$data
[
'create_time'
] = time();
$data
[
'update_time'
] = time();
if
(
$data
[
'pay_id'
] == 1) {
$data
[
'order_status'
] = 11;
//已付款
$data
[
'status'
] =
'1'
;
}
else
{
$data
[
'order_status'
] = 10;
//待付款
$data
[
'status'
] =
'1'
;
}
//函數調用 返回信息
$this
->Callback_url(
$data
);
}
else
{
$this
->error(
$o_model
->getError());
}
}
else
{
$this
->error(
$o_model
->getError());
}
}
/**
* 回調信息函數
* @param type $data
*/
public
function
Callback_url(
$data
) {
$o_model
= D(
"Wine/Orders"
);
$add_id
=
$o_model
->add(
$data
);
if
(!
$add_id
) {
$this
->error(
"訂單提交失敗,請稍后重試!"
);
}
if
(
'4'
==
$data
[
'pay_id'
]) {
if
(
'4'
==
$data
[
'pay_id'
]) {
//微信支付
$msg
=
'正在為您跳轉到微信支付頁面,請等待……'
;
$url
=
"/index.php/wine/wxpay/index/?o_id=$add_id"
;
}
$this
->success(
"訂單提交成功!"
.
$msg
,
$url
);
}
|
3.[重點!!!] WxpayController .class.php微信支付控制器,實現對微信接口的調用
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
|
<?php
/**
* 微信支付接口調用
*/
namespace
Wine\Controller;
use
Common\Controller\HomebaseController;
class
WxpayController
extends
HomebaseController {
public
function
_initialize() {
parent::_initialize();
Vendor(
"WxpayAPI/example/log"
);
//訂單數據寫入日志
//注: 引入第三方類庫中的微信接口文件,對於文件名含有.的,皆用#代替連接才能引入,后綴名不寫。
Vendor(
"WxpayAPI/example/WxPay#JsApiPay"
);
Vendor(
"WxpayAPI/lib/WxPay#Config"
);
Vendor(
"WxpayAPI/lib/WxPay#Data"
);
Vendor(
"WxpayAPI/lib/WxPay#Exception"
);
Vendor(
"WxpayAPI/lib/WxPay#Notify"
);
Vendor(
"WxpayAPI/lib/WxPay#Api"
);
//初始化日志
$logHandler
=
new
\CLogFileHandler(
"/projects/wine.huishuocs.com/data/pay_log/"
.
date
(
'Y-m-d'
) .
'.log'
);
$log
= \Log::Init(
$logHandler
, 15);
$this
->model = D(
"Wine/Orders"
);
$this
->url = MODULE_NAME .
'/'
. CONTROLLER_NAME .
'/index'
;
}
/**
* 顯示支付頁面
*
*/
public
function
index() {
// 判斷當前訂單是否被支付
$orderid
= I(
"get.o_id"
, 0,
"intval"
);
$orderid
||
$this
->error(
"非法操作!"
);
$this
->assign(
'orderid'
,
$orderid
);
$info
=
$this
->model->findone(
array
(
"a.id"
=>
$orderid
,
'a.status'
=>
array
(
'neq'
,
'-1'
)));
$info
||
$this
->error(
"暫未查詢到該訂單!"
);
//10代表訂單待支付的狀態
if
(
$info
[
'order_status'
] != 10) {
$this
->error(
"訂單已支付!"
);
}
//①、獲取用戶openid
$tools
=
new
\JsApiPay();
$openId
=
$tools
->GetOpenid(); #無法使用
//初始化日志
\Log::INFO(
'訂單'
. var_export(
$info
, true));
$out_trade_no
= \WxPayConfig::MCHID .
date
(
"YmdHis"
);
$this
->model->where(
array
(
"id"
=>
$orderid
))->save(
array
(
'out_trade_no'
=>
$out_trade_no
));
// $openId ="123"; #無法使用
//②、統一下單
$input
=
new
\WxPayUnifiedOrder();
$input
->SetBody(
$info
[
'mode_name'
]);
$input
->SetAttach(
$orderid
);
$input
->SetOut_trade_no(
$out_trade_no
);
// $input->SetTotal_fee($orderArr['total_price']*100);實際支付價格
$input
->SetTotal_fee(
$info
[
'pay_price'
]*100);
//測試時請將支付價格改為0.01,土豪請避開此注釋
$this
->assign(
'pay_price'
,
$info
[
'pay_price'
]);
$input
->SetTime_start(
date
(
"YmdHis"
));
$input
->SetTime_expire(
date
(
"YmdHis"
, time() + 600));
// $input->SetGoods_tag("test");# 優惠券
$input
->SetNotify_url(
'http://'
.
$_SERVER
[
'HTTP_HOST'
] .
"/index.php/Wine/Wxpay/callback"
); //回調地址
$input
->SetTrade_type(
"JSAPI"
);
$input
->SetOpenid(
$openId
);
$order
= \WxPayApi::unifiedOrder(
$input
);
// echo '<font color="#f00"><b>統一下單支付單信息</b></font><br/>';
// $this->printf_info($order);//打印參數
$this
->assign(
'o_id'
,
$orderid
);
$this
->assign(
'jsApiParameters'
,
$tools
->GetJsApiParameters(
$order
));
//獲取共享收貨地址js函數參數
// $this->assign('editAddress', $tools->GetEditAddressParameters());
$this
->display(
'wxpay'
);
exit
;
}
/**
* 打印輸出數組信息
* @param type $data
*/
public
function
printf_info(
$data
) {
foreach
(
$data
as
$key
=>
$value
) {
echo
"<font color='#00ff55;'>$key</font> : $value <br/>"
;
}
}
/* 支付成功回調函數 */
public
function
callback() {
/* 返回給微信服務器 */
// $mes = array(
// 'return_code' => 'SUCCESS',
// 'return_msg' => 'OK'
// );
// $this->ajaxReturn($mes, 'XML');
$logHandler
=
new
\CLogFileHandler(
"/projects/wine.huishuocs.com/data/pay_log/"
.
date
(
'Y-m-d'
) .
'.log'
);
$log
= \Log::Init(
$logHandler
, 15);
//$streamData = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$streamData
=
file_get_contents
(
'php://input'
);
if
(
$streamData
!=
''
) {
$arr
=
$this
->xmlToArray(
$streamData
);
\Log::INFO(
'支付'
. var_export(
$arr
, true));
}
else
{
$ret
= false;
}
// 回調值
if
(!
empty
(
$arr
)) {
# 數據
\Log::INFO(
'數據1'
. var_export(
$arr
, true));
#修改訂單狀態
$out_trade_no
=
$arr
[
'out_trade_no'
];
$newArr
=
array
(
'order_status'
=> 11,
'status'
=>1);
$this
->model->where(
array
(
"out_trade_no"
=>
$out_trade_no
))->save(
$newArr
);
$info
=
$this
->model->findone(
array
(
"a.out_trade_no"
=>
$out_trade_no
,
'a.status'
=>
array
(
'neq'
,
'-1'
)));
$sql
=
$this
->model->getLastSql();
\Log::INFO(
'數據2'
.
$sql
);
#添加支付記錄pay
$pay
=
array
(
'payment_code'
=>
'wxpay'
,
'trade_no'
=>
$info
[
'order_code'
],
'out_trade_no'
=>
$out_trade_no
,
'order_id'
=>
$info
[
'id'
],
'create_time'
=>time()
);
M(
'payment_record'
)->add(
$pay
);
}
/* 返回給微信服務器 */
$mes
=
array
(
'return_code'
=>
'SUCCESS'
,
'return_msg'
=>
'OK'
);
$this
->ajaxReturn(
$mes
,
'XML'
);
}
//將XML轉為array
public
function
xmlToArray(
$xml
) {
//禁止引用外部xml實體
libxml_disable_entity_loader(true);
$values
= json_decode(json_encode(simplexml_load_string(
$xml
,
'SimpleXMLElement'
, LIBXML_NOCDATA)), true);
return
$values
;
}
}
?>
|
4.前端微信支付頁面wxpay.html
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
|
<html>
<head>
<meta http-equiv=
"content-type"
content=
"text/html;charset=utf-8"
/>
<meta name=
"viewport"
content=
"width=device-width, initial-scale=1"
/>
<link href=
"__TMPL__Public/css/weui.css"
type=
"text/css"
rel=
"stylesheet"
/>
<title>微信訂單支付</title>
<script type=
"text/javascript"
>
//調用微信JS api 支付
function
jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest'
,
<php>
echo
$jsApiParameters
; </php>,
function
(res) {
WeixinJSBridge.log(res.err_msg);
if
(res.err_msg ==
"get_brand_wcpay_request:ok"
) {
// alert(res.err_code + res.err_desc + res.err_msg);
// 成功跳轉頁面
window.location.href =
'{:U("Orders/pay_ok",array("o_id"=>$o_id))}'
;
}
else
{
// 統一跳轉
}
}
);
}
function
callpay()
{
if
(typeof WeixinJSBridge ==
"undefined"
) {
if
(document.addEventListener) {
document.addEventListener(
'WeixinJSBridgeReady'
, jsApiCall, false);
}
else
if
(document.attachEvent) {
document.attachEvent(
'WeixinJSBridgeReady'
, jsApiCall);
document.attachEvent(
'onWeixinJSBridgeReady'
, jsApiCall);
}
}
else
{
jsApiCall();
}
}
</script>
</head>
<body>
<br/>
<div
class
=
"container"
id=
"container"
><div
class
=
"msg"
>
<div
class
=
"weui_msg"
>
<div
class
=
"weui_icon_area"
><i
class
=
"weui_icon_success weui_icon_msg"
></i></div>
<div
class
=
"weui_text_area"
>
<h2
class
=
"weui_msg_title"
>訂單已生成</h2>
<p
class
=
"weui_msg_desc"
>該筆訂單支付金額為:<php>
echo
$pay_price
;</php></p>
</div>
<div
class
=
"weui_opr_area"
>
<p
class
=
"weui_btn_area"
>
<a href=
"javascript:;"
class
=
"weui_btn weui_btn_primary"
onclick=
"callpay()"
>立即支付</a>
<!--<a href=
"{:U('Order/pay_ok',array('o_id'=>$_GET['o_id']))}"
class
=
"weui_btn weui_btn_default"
>取消支付</a>-->
</p>
</div>
<!-- <div
class
=
"weui_extra_area"
>
<a href=
"/wap/order/order_det/<?php echo $order['id']?>.html"
>查看詳情</a>
</div>-->
</div>
</div>
</div>
</body>
</html>
|
5.支付成功跳轉到OrderController.class.php ,訂單支付完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* 支付頁面
*/
public
function
pay_ok() {
$o_id
= I(
"get.o_id"
, 0,
"intval"
);
$info
=
$this
->model->findone(
array
(
"a.id"
=>
$o_id
,
'a.status'
=>
array
(
'neq'
,
'-1'
)));
if
(
empty
(
$info
)) {
# 獲取最新可用的商品編號
$goods
= D(
'Goods'
)->where(
array
(
'status'
=>
'1'
))->order(
'id desc'
)->find();
$this
->error(
"該訂單不存在,請重新正確進入"
, U(
'Goods/sale'
,
array
(
'id'
=>
$goods
[
'id'
])));
}
$this
->assign(
'imgurl'
,
"/wine/img/ok.png"
);
$this
->assign(
'tips'
,
"訂購成功"
);
if
(
'4'
==
$info
[
'pay_id'
]) {
//微信支付成功
$this
->assign(
$info
);
$this
->display();
}
else
{
$this
->assign(
$info
);
$this
->assign(
'tips'
,
"訂購失敗"
);
$this
->assign(
'imgurl'
,
"/wine/img/nook.png"
);
$this
->display();
}
}
|
到此,微信支付流程結束。
- 支付寶支付
話不多說,直接上代碼!
注:
1.支付文件是從支付寶上直接拿過來的 2.依舊是TP框架
【1】將文件放入第三方類庫:
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
|
(1)
* 類名:AlipayConfig.php
* 功能:支付寶配置文件
* 修改配置:
// MD5密鑰,安全檢驗碼,由數字和字母組成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
$alipay_config
[
'key'
] =
''
;
//(**從支付寶中獲取**)
// 服務器異步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
$alipay_config
[
'notify_url'
] =
'http://'
.
$_SERVER
[
'SERVER_NAME'
] .
'/index.php/Wine/PayCallback/alipay_notify'
;
// 頁面跳轉同步通知頁面路徑 需http://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
$alipay_config
[
'return_url'
] =
'http://'
.
$_SERVER
[
'SERVER_NAME'
] .
'/index.php?g=Wine&m=Orders&a=alipay_return'
;
(2)
* 類名:AlipayNotify.php
* 功能:支付寶通知處理類
* 詳細:處理支付寶各接口通知返回
(3)
* 類名:Alipay.php
* 功能:手機網站支付接口接入頁
* 詳細:處理支付寶各接口通知返回
class
Alipay {
public
function
submit(
$params
) {
//建立請求
$alipaySubmit
=
new
AlipaySubmit(
$alipay_config
);
$html_text
=
$alipaySubmit
->buildRequestForm(
$parameter
,
"get"
,
"確認"
);
return
'<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
<html>
<head>
<meta http-equiv=
"Content-Type"
content=
"text/html; charset=utf-8"
>
<title>支付寶支付</title>
</head>
' . $html_text . '
</body>
</html>';
}
}
(4)
* 類名:notify_url.php
* 功能:支付寶服務器異步通知頁面
* 詳細:處理支付寶各接口通知返回
|

Paste_Image.png
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
|
【2】支付業務邏輯
(1)GoodsController.
class
.php 下提交訂單 ajax_sure()
public
function
ajax_sure() {<br>
$data
[
'order_code'
] =
$order_code
;
$addr
[0] =
$_POST
[
'prov'
];
$addr
[1] =
$_POST
[
'city'
];
$addr
[2] =
$_POST
[
'dist'
];
$addr
[3] =
$_POST
[
'area'
];
$data
[
'area'
] = serialize(
$addr
);
$data
[
'create_time'
] = time();
$data
[
'update_time'
] = time();
$data
[
'ip'
] =
$_SERVER
[
'REMOTE_ADDR'
];
if
(
$data
[
'pay_id'
] == 1) {
$data
[
'order_status'
] = 11;
//已付款
$data
[
'status'
] =
'1'
;
}
else
{
$data
[
'order_status'
] = 10;
//待付款
$data
[
'status'
] =
'1'
;
}
//函數調用 返回信息
$this
->Callback_url(
$data
);
}
/**
* 回調信息函數
* @param type $data
*/
public
function
Callback_url(
$data
) {
$o_model
= D(
"Wine/Orders"
);
$add_id
=
$o_model
->add(
$data
);
if
(!
$add_id
) {
$this
->error(
"訂單提交失敗,請稍后重試!"
);
}<br>
if
(
'3'
==
$data
[
'pay_id'
]) {
//支付寶支付
$msg
=
'正在為您跳轉到支付寶支付頁面,請等待……'
;
$url
= U(
"Pay/doalipay"
,
array
(
'o_id'
=>
$add_id
));
}
$this
->success(
"訂單提交成功!"
.
$msg
,
$url
);
}
(2)PayController.
class
.php 下
/**
* 支付頁面
*/
public
function
doalipay() {
$o_id
= I(
"get.o_id"
, 0,
"intval"
);
$info
=
$this
->model->findone(
array
(
"a.id"
=>
$o_id
,
'a.status'
=>
array
(
'neq'
,
'-1'
)));
//10代表訂單待支付的狀態
if
(
$info
[
'order_status'
] != 10) {
$this
->error(
"訂單已支付!"
);
}
vendor(
"Payment.Alipay.Alipay"
);
$alipay
=
new
\Alipay();
$param
[
'order_sn'
] =
$info
[
'order_code'
];
// $param['order_amount'] = $info['pay_price'];
$param
[
'order_amount'
] = 0.01;
//測試支付時,將支付價格設為0.01元,土豪朋友忽略此提示O(∩_∩)O~
$param
[
'order_subject'
] =
'支付寶支付測試'
;
$param
[
'return_url'
] =
'http://'
.
$_SERVER
[
'SERVER_NAME'
] .
'/index.php/Wine/Orders/pay_ok/o_id/'
.
$o_id
;
$return
=
$alipay
->submit(
$param
);
echo
$return
;
exit
;
}
|
就是這么簡單幾步,到此,支付寶支付的流程就已經結束了。