代碼中包含四個(gè)文件createUrl.php、ArrayToXML.php、returnGoodsUrl.php、notifyUrl.php 。
createUrl.php:創(chuàng)建微信二維碼支付鏈接
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
|
<?php /** * @author chantrans * 本頁面的作用是生成商品二維碼鏈接 */ //測試 echo createUrl( "12314124" ); /** * 產(chǎn)生隨機(jī)字符串 */ function getNonceStr() { $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' ; $noceStr = "" ; for ( $i = 0; $i < 32; $i ++) { $noceStr .= $chars [ mt_rand(0, strlen ( $chars ) - 1) ]; } $oldNonceStr = $noceStr ; return $noceStr ; } /** * 二維碼掃碼鏈接構(gòu)造方式: * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXXX&productid=XXXXXX×tamp=XXXXXX&noncestr=XXXXXX * appid 是字段名稱:公眾號id;字段來源:商戶注冊具有支付權(quán)限的公眾號成功后即可獲得;傳入方式:由商戶直接傳入。 timestamp 是字段名稱:時(shí)間戳;字段來源:商戶生成從1970 年1 月1 日00:00:00 至今的秒數(shù),即當(dāng)前的時(shí)間;由商戶生成后傳入。取值范圍:32 字符以下 noncestr 是字段名稱:隨機(jī)字符串;字段來源:商戶生成的隨機(jī)字符串;取值范圍:長度為32 個(gè)字符以下。由商戶生成后傳入。取值范圍:32 字符以下 productid 是字段名稱:商品唯一id;字段來源:商戶需要定義并維護(hù)自己的商品id,這個(gè)id 與一張訂單等價(jià),微信后臺憑借該id 通過Post商戶后臺獲取交易必須信息。由商戶生成后傳入。取值范圍:32字符以下 sign 是字段名稱:簽名;字段來源:對前面的其他字段與appKey 按照字典序排序后,使用SHA1 算法得到的結(jié)果。由商戶生成后傳入。參與sign 簽名的字段包括:appid、timestamp、noncestr、productid 以及appkey。 */ function createUrl( $productid ){ $app_id = "wxbce29784bdd01454" ; //公眾號appid $app_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ; //公眾號支付請求中用于加密的密鑰Key,可驗(yàn)證商戶唯一身份,PaySignKey對應(yīng)于支付場景中的appKey值。 $nonce_str =getNonceStr(); $time_stamp = strtotime ( "now" ); //對所有需要傳入的參數(shù)加上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到該腳本,該腳本負(fù)責(zé)返回與商品ID對應(yīng)的商品信息。
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
|
<?php include 'ArrayToXML.php' ; header( 'Content-Type:text/xml' ); /*** * 該腳本為當(dāng)公眾該平臺接到Native(原生)支付請求時(shí),會調(diào)用此回調(diào)URL獲取商品信息。 */ /** 第一步:接收微信服務(wù)器post過來的信息 (1)OpenId,點(diǎn)擊鏈接準(zhǔn)備購買商品的用戶openid (2)AppId,公眾帳號的appid (3)IsSubscribe,標(biāo)記用戶是否訂閱該公眾帳號,1 為關(guān)注,0 為未關(guān)注 (4)ProductId,第三方的商品ID號 (5)TimeStamp,時(shí)間戳 (6)NonceStr,隨機(jī)串 (7)AppSignature,參數(shù)的加密簽名,是根據(jù)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等訂單信息保存在數(shù)據(jù)庫中 * */ function createTradeId(){ $curDateTime = date ( "YmdHis" ); //date_default_timezone_set(PRC); $strDate = date ( "Ymd" ); $strTime = date ( "His" ); //4位隨機(jī)數(shù) $randNum = rand(1000, 9999); //10位序列號,可以自行調(diào)整。 $strReq = $strTime . $randNum ; /* 商家的定單號 */ $mch_vno = $curDateTime . $strReq ; /********************/ /*todo 保存訂單信息到數(shù)據(jù)庫中*/ /********************/ return $mch_vno ; } /** * 第三步:生成商品詳情pakage * @param string $body 商品描述 * @param string $total_fee 訂單總金額,單位為分。 * @param string $out_trade_no 商戶系統(tǒng)內(nèi)部的訂單號 * @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" ; //費(fèi)用類型,這里1為默認(rèn)的人民幣 $input_charset = "GBK" ; //字符集,這里將統(tǒng)一使用GBK $notify_url = "http://xxxxxx.com/Wxpay/notify.html" ;//支付成功后將通知該地址 $out_trade_no =createTradeId(); //訂單號,商戶需要保證該字段對于本商戶的唯一性 $partner = "XXXXXXXX" ; //商戶號 $spbill_create_ip = $ip ; //訂單生成的機(jī)器IP $partnerKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXX" ; //這個(gè)值和以上其他值不一樣是:簽名需要它,而最后組成的傳輸字符串不能含有它。這個(gè)key是需要商戶好好保存的。 //首先第一步:對原串進(jìn)行簽名,注意這里不要對任何字段進(jìn)行編碼。這里是將參數(shù)按照key=value進(jìn)行字典排序后組成下面的字符串,在這個(gè)字符串最后拼接上key=XXXX。由于這里的字段固定,因此只需要按照這個(gè)順序進(jìn)行排序即可。 $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; //然后第二步,對每個(gè)參數(shù)進(jìn)行url轉(zhuǎn)碼。 $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 ); //然后進(jìn)行最后一步,這里按照key=value除了sign外進(jìn)行字典序排序后組成下列的字符串,最后再串接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,方便最后進(jìn)行整體簽名時(shí)取用 return $completeString ; } //模擬js中的encodeURIComponent方法 function encodeURIComponent( $str ) { $revert = array ( '%21' => '!' , '%2A' => '*' , '%27' => "'" , '%28 '=>' ( ', ' %29 '=>' )'); return strtr (rawurlencode( $str ), $revert ); } /** 第四步: 為了返回Package 數(shù)據(jù),回調(diào)URL 必須返回一個(gè)xml 格式的返回?cái)?shù)據(jù),形如: <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> 對于一些第三方覺得商品已經(jīng)過期或者其他錯誤的情況,可以在RetCode 和 RetErrMsg 中體現(xiàn)出來,RetCode 為0 表明正確,可以定義其他錯誤;當(dāng)定義其他錯誤時(shí), 可以在RetErrMsg 中填上UTF8 編碼的錯誤提示信息,比如“該商品已經(jīng)下架”,客戶端會 直接提示出來。 **/ $data = array ( "AppId" => $AppId , "Package" =>getPackage( "測試商品" ,100, "201311291504302501231" ), "TimeStamp" => strtotime (), "NonceStr" => $NonceStr , "RetCode" =>0, //RetCode 為0 表明正確,可以定義其他錯誤;當(dāng)定義其他錯誤時(shí),可以在RetErrMsg 中填上UTF8 編碼的錯誤提示信息,比如“該商品已經(jīng)下架”,客戶端會直接提示出來。 "RetErrMsg" => "正確返回" , "AppSignature" => $AppSignature , "SignMethod" => "sha1" ); //返回生成的xml數(shù)據(jù) echo ArrayToXML::arrtoxml( $data ); |
notifyUrl.php :用戶支付商品后,微信服務(wù)器會將商品信息、支付結(jié)果、用戶的openId等重要信息以get和post方式傳遞到該鏈接上,該腳本接收這些信息,并根據(jù)支付信息做發(fā)貨處理,最后返回給微信服務(wù)器success,告知他們,我們已經(jīng)處理到此通知。否則,微信服務(wù)器將會定期重新發(fā)起通知。
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 進(jìn)行,采用post 機(jī)制。返回通知中的參數(shù)一致,url包含如下內(nèi)容: 見【微信公眾號支付】公眾號支付接口文檔V2.2.pdf 中通知接口部分 同時(shí),在postData 中還將包含xml 數(shù)據(jù)。數(shù)據(jù)如下: <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> 商戶需要對這些參數(shù)進(jìn)行保存和判斷用戶的支付狀態(tài) */ // 獲取微信通知接口postData信息 $postdata = file_get_contents ( "php://input" ); $postObj = simplexml_load_string ( $postdata , 'SimpleXMLElement' , LIBXML_NOCDATA ); $trade_state = $_GET [ "trade_state" ]; //支付狀態(tài) $out_trade_no = $_GET [ "out_trade_no" ]; //訂單號 /***************** Todo 還有很多其他參數(shù)需要保存起來,參數(shù)列表詳見文檔 **************************/ if ( $trade_state ==0){ echo "success" ; } else { echo "false" ; } |
ArrayToXML.php:該腳本的作用是將數(shù)組轉(zhuǎn)換成為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(); } } |
以上就是本實(shí)例的全部內(nèi)容了,希望大家能喜歡