http://www.php.cn/php-weizijiaocheng-358904.html
最近一段弄微信網頁掃碼支付,看官方文檔是暈頭轉向。其實掃碼支付很簡單,只是讓官網指來指去變的很麻煩,我想如果有個實例,會容易很多。下面就把實例分享給大家
代碼中包含四個文件createUrl.php、ArrayToXML.php、returnGoodsUrl.php、notifyUrl.php 。
createUrl.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
|
<?php
/**
* @author chantrans
* 本頁面的作用是生成商品二維碼鏈接
*/
//測試
echo
createUrl( "12314124" );
/**
* 產生隨機字符串
*/
function
getNonceStr()
{
$chars
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' ;
$noceStr
= "" ;
for
( $i = 0; $i < 32; $i ++) {
$noceStr
.= $chars [ mt_rand(0, strlen ( $chars ) - 1) ];
}
$oldNonceStr
= $noceStr ;
return
$noceStr ;
}
/**
* 二維碼掃碼鏈接構造方式:
* weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXXX&productid=XXXXXX×tamp=XXXXXX&noncestr=XXXXXX
*
appid 是字段名稱:公眾號id;字段來源:商戶注冊具有支付權限的公眾號成功后即可獲得;傳入方式:由商戶直接傳入。
timestamp 是字段名稱:時間戳;字段來源:商戶生成從1970 年1 月1 日00:00:00 至今的秒數,即當前的時間;由商戶生成后傳入。取值范圍:32 字符以下
noncestr 是字段名稱:隨機字符串;字段來源:商戶生成的隨機字符串;取值范圍:長度為32 個字符以下。由商戶生成后傳入。取值范圍:32 字符以下
productid 是字段名稱:商品唯一id;字段來源:商戶需要定義並維護自己的商品id,這個id 與一張訂單等價,微信后台憑借該id
通過Post商戶后台獲取交易必須信息。由商戶生成后傳入。取值范圍:32字符以下
sign 是字段名稱:簽名;字段來源:對前面的其他字段與appKey 按照字典序排序后,使用SHA1 算法得到的結果。由商戶生成后傳入。
參與sign 簽名的字段包括:appid、timestamp、noncestr、productid 以及appkey。
*/
function
createUrl( $productid ){
$app_id
= "wxbce29784bdd01454" ; //公眾號appid
$app_key
= "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ;
//公眾號支付請求中用於加密的密鑰Key,可驗證商戶唯一身份,PaySignKey對應於支付場景中的appKey值。
$nonce_str
=getNonceStr();
$time_stamp
= strtotime ( "now" );
//對所有需要傳入的參數加上appkey作一次key=value字典序的排序
$keyvaluestring
= "appid=" . $app_id . "&appkey=" . $app_key . "&noncestr=" . $nonce_str . "&productid=" . $productid . "×tamp=" . $time_stamp ;
$sign
= sha1( $keyvaluestring ). "" ;
$url
= "weixin://wxpay/bizpayurl?sign=" . $sign . "&appid=" . $app_id . "&productid=" . $productid . "×tamp=" . $time_stamp . "&noncestr=" . $nonce_str . "" ;
return
$url ;
}
|
returnGoodsUrl.php:用戶掃描二維碼鏈接后,微信將鏈接中的商品ID、openId以及其他信息post到該腳本,該腳本負責返回與商品ID對應的商品信息。
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
|
<?php
include
'ArrayToXML.php' ;
header(
'Content-Type:text/xml'
);
/***
* 該腳本為當公眾該平台接到Native(原生)支付請求時,會調用此回調URL獲取商品信息。
*/
/**
第一步:接收微信服務器post過來的信息
(1)OpenId,點擊鏈接准備購買商品的用戶openid
(2)AppId,公眾帳號的appid
(3)IsSubscribe,標記用戶是否訂閱該公眾帳號,1 為關注,0 為未關注
(4)ProductId,第三方的商品ID號
(5)TimeStamp,時間戳
(6)NonceStr,隨機串
(7)AppSignature,參數的加密簽名,是根據2.7 支付簽名(paySign)生成方法中所講的簽名方式生成的簽名
(8)SignMethod,簽名方式,目前只支持“SHA1”。該字段不參與簽名
**/
$postdata
= file_get_contents ( "php://input" );
$postObj
= simplexml_load_string ( $postdata , 'SimpleXMLElement' , LIBXML_NOCDATA );
$openId
= $postObj ->OpenId;
$AppId
= $postObj ->AppId;
$IsSubscribe
= $postObj ->IsSubscribe;
$ProductId
= $postObj ->ProductId;
$TimeStamp
= $postObj ->TimeStamp;
$NonceStr
= $postObj ->NonceStr;
$AppSignature
= $postObj ->AppSignature;
$SignMethod
= $postObj ->SignMethod;
/**
* 第二步,生成訂單號,並且和商品信息,用戶openID等訂單信息保存在數據庫中
*
*/
function
createTradeId(){
$curDateTime
= date ( "YmdHis" );
//date_default_timezone_set(PRC);
$strDate
= date ( "Ymd" );
$strTime
= date ( "His" );
//4位隨機數
$randNum
= rand(1000, 9999);
//10位序列號,可以自行調整。
$strReq
= $strTime . $randNum ;
/* 商家的定單號 */
$mch_vno
= $curDateTime . $strReq ;
/********************/
/*todo 保存訂單信息到數據庫中*/
/********************/
return
$mch_vno ;
}
/**
* 第三步:生成商品詳情pakage
* @param string $body 商品描述
* @param string $total_fee 訂單總金額,單位為分。
* @param string $out_trade_no 商戶系統內部的訂單號
* @return $package
*/
function
getPackage( $body , $total_fee , $out_trade_no ){
$ip
=
$_SERVER
[
"REMOTE_ADDR"
];
if
(
$ip
==
"::1"
||
empty
(
$ip
)){
$ip
=
"127.0.0.1"
;
}
$banktype
= "WX" ;
$fee_type
= "1" ; //費用類型,這里1為默認的人民幣
$input_charset
= "GBK" ; //字符集,這里將統一使用GBK
$notify_url
= "http://xxxxxx.com/Wxpay/notify.html" ;//支付成功后將通知該地址
$out_trade_no
=createTradeId(); //訂單號,商戶需要保證該字段對於本商戶的唯一性
$partner
= "XXXXXXXX" ; //商戶號
$spbill_create_ip
= $ip ; //訂單生成的機器IP
$partnerKey
= "XXXXXXXXXXXXXXXXXXXXXXXXXXX" ; //這個值和以上其他值不一樣是:簽名需要它,而最后組成的傳輸字符串不能含有它。這個key是需要商戶好好保存的。
//首先第一步:對原串進行簽名,注意這里不要對任何字段進行編碼。這里是將參數按照key=value進行字典排序后組成下面的字符串,在這個字符串最后拼接上key=XXXX。
由於這里的字段固定,因此只需要按照這個順序進行排序即可。
$signString
= "bank_type=" . $banktype . "&body=" . $body . "&fee_type=" . $fee_type . "&input_charset=" . $input_charset ."
¬ify_url=
".$notify_url."
&out_trade_no=
".$out_trade_no."
&partner=
".$partner."
&spbill_create_ip=".
$spbill_create_ip
.
"&total_fee="
.
$total_fee
.
"&key="
.
$partnerKey
;
$md5SignValue
= ( "" . strtoupper (md5(( $signString ))));
//echo $md5SignValue;
//然后第二步,對每個參數進行url轉碼。
$banktype
= encodeURIComponent( $banktype );
$body
=encodeURIComponent(
$body
);
$fee_type
=encodeURIComponent(
$fee_type
);
$input_charset
= encodeURIComponent( $input_charset );
$notify_url
= encodeURIComponent( $notify_url );
$out_trade_no
= encodeURIComponent( $out_trade_no );
$partner
= encodeURIComponent( $partner );
$spbill_create_ip
= encodeURIComponent( $spbill_create_ip );
$total_fee
= encodeURIComponent( $total_fee );
//然后進行最后一步,這里按照key=value除了sign外進行字典序排序后組成下列的字符串,最后再串接sign=value
$completeString
= "bank_type=" . $banktype . "&body=" . $body . "&fee_type=" . $fee_type . "&input_charset=" . $input_charset ."
.¬ify_url=
".$notify_url."
&out_trade_no=
".$out_trade_no."
&partner=
".$partner."
&spbill_create_ip=
".$spbill_create_ip."
&total_fee=".
$total_fee
;
$completeString
= $completeString . "&sign=" . $md5SignValue ;
$oldPackageString
= $completeString ; //記住package,方便最后進行整體簽名時取用
return
$completeString ;
}
//模擬js中的encodeURIComponent方法
function
encodeURIComponent( $str ) {
$revert
= array ( '%21' => '!' , '%2A' => '*' , '%27' => "'" , '%28 '=>' ( ', ' %29 '=>' )');
return
strtr (rawurlencode( $str ), $revert );
}
/**
第四步:
為了返回Package 數據,回調URL 必須返回一個xml 格式的返回數據,形如:
<xml>
<AppId><![CDATA[wwwwb4f85f3a797777]]></AppId>
<Package><![CDATA[a=1&url=http%3A%2F%2Fwww.qq.com]]></Package>
<TimeStamp> 1369745073</TimeStamp>
<NonceStr><![CDATA[iuytxA0cH6PyTAVISB28]]></NonceStr>
<RetCode>0</RetCode>
<RetErrMsg><![CDATA[ok]]></ RetErrMsg>
<AppSignature><![CDATA[53cca9d47b883bd4a5c85a9300df3da0cb48565c]]>
</AppSignature>
<SignMethod><![CDATA[sha1]]></ SignMethod >
</xml>
對於一些第三方覺得商品已經過期或者其他錯誤的情況,可以在RetCode 和
RetErrMsg 中體現出來,RetCode 為0 表明正確,可以定義其他錯誤;當定義其他錯誤時,
可以在RetErrMsg 中填上UTF8 編碼的錯誤提示信息,比如“該商品已經下架”,客戶端會
直接提示出來。
**/
$data
=
array
(
"AppId"
=>
$AppId
,
"Package"
=>getPackage(
"測試商品"
,100,
"201311291504302501231"
),
"TimeStamp"
=>
strtotime
(),
"NonceStr"
=>
$NonceStr
,
"RetCode"
=>0,
//RetCode 為0 表明正確,可以定義其他錯誤;當定義其他錯誤時,可以在RetErrMsg 中填上UTF8 編碼的錯誤提示信息,
比如“該商品已經下架”,客戶端會直接提示出來。
"RetErrMsg"
=>
"正確返回"
,
"AppSignature"
=>
$AppSignature
,
"SignMethod"
=>
"sha1"
);
//返回生成的xml數據
echo
ArrayToXML::arrtoxml( $data );
|
notifyUrl.php :用戶支付商品后,微信服務器會將商品信息、支付結果、用戶的openId等重要信息以get和post方式傳遞到該鏈接上,該腳本接收這些信息,並根據支付信息做發貨處理,最后返回給微信服務器success,告知他們,我們已經處理到此通知。否則,微信服務器將會定期重新發起通知。
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
|
<?
/**
后台通知通過請求中的notify_url 進行,采用post 機制。返回通知中的參數一致,url包含如下內容:
見【微信公眾號支付】公眾號支付接口文檔V2.2.pdf 中通知接口部分
同時,在postData 中還將包含xml 數據。數據如下:
<xml>
<OpenId><![CDATA[111222]]></OpenId>
<AppId><![CDATA[wwwwb4f85f3a797777]]></AppId>
<IsSubscribe>1</IsSubscribe>
<TimeStamp> 1369743511</TimeStamp>
<NonceStr><![CDATA[jALldRTHAFd5Tgs5]]></NonceStr>
<AppSignature><![CDATA[bafe07f060f22dcda0bfdb4b5ff756f973aecffa]]>
</AppSignature>
<SignMethod><![CDATA[sha1]]></ SignMethod >
</xml>
商戶需要對這些參數進行保存和判斷用戶的支付狀態
*/
// 獲取微信通知接口postData信息
$postdata
= file_get_contents ( "php://input" );
$postObj
= simplexml_load_string ( $postdata , 'SimpleXMLElement' , LIBXML_NOCDATA );
$trade_state
= $_GET [ "trade_state" ]; //支付狀態
$out_trade_no
= $_GET [ "out_trade_no" ]; //訂單號
/***************** Todo 還有很多其他參數需要保存起來,參數列表詳見文檔 **************************/
if
(
$trade_state
==0){
echo
"success" ;
}
else
{
echo
"false" ;
}
|
ArrayToXML.php:該腳本的作用是將數組轉換成為xml。
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
|
<?php
class
ArrayToXML
{
/**
* @param array $arr
* @return string XML
*/
public
static function arrtoxml( $arr , $dom =0, $item =0)
{
if
(! $dom ){
$dom
= new DOMDocument( "1.0" );
}
if
(!
$item
){
$item
= $dom ->createElement( "xml" );
$dom
->appendChild(
$item
);
}
foreach
( $arr as $key => $val ){
$itemx
= $dom ->createElement( is_string ( $key )? $key : "item" );
$item
->appendChild(
$itemx
);
if
(! is_array ( $val )){
$text
= $dom ->createTextNode( $val );
$itemx
->appendChild(
$text
);
}
else
{
self::arrtoxml(
$val
,
$dom
,
$itemx
);
}
}
return
$dom ->saveXML();
}
}
|
以上就是php實現微信掃碼支付的示例代碼分享的詳細內容,更多請關注php中文網其它相關文章!