程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP支付寶接口RSA驗證

PHP支付寶接口RSA驗證

編輯:關於PHP編程

這兩天一直困擾的PHP RSA簽名驗證問題終於解決了,由於之前RSA接觸的不多,再加上官方至今還未有PHP的SDK可供參考,因此走了一些彎路,寫在這裡和大家分享。     雖然支付寶官方還未提供相關SDK,PHP確實可以實現RSA方式的簽名,這點其實很重要,由於不熟悉,在遇到困難的時候,經常會不由自主地想到是否PHP不支持RSA簽名,干脆用MD5得了,這樣就沒有了前進的動力。其實說穿了MD5和RSA簽名,不同的只是簽名方式的區別,其他的都一樣,因此我這裡主要說一下如何用RSA進行簽名和驗簽。       首先你需要准備下面的東西:     php的openssl擴展裡已經封裝好了驗簽的方法openssl_verify。     如果在Windows下的php.ini需要開啟Openssl模塊: extension=php_openssl.dll       商戶私鑰:     即RSA私鑰,按照手冊,按以下方式生成:       openssl genrsa -out rsa_private_key.pem 1024        商戶公鑰:     即RSA私鑰,按照手冊,按以下方式生成:     openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem       生成之後,按照手冊的說明,需要在簽約平台上傳公鑰,需要注意的是,上傳的時候需要把所有的注釋和換行都去掉。        另外手冊中還有如下命令:     openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt       該命令將RSA私鑰轉換成PKCS8格式,對於PHP來說,不需要。        支付寶公鑰:     根據手冊,在簽約平台獲得。     如果你直接復制下來的話,會得到一個字符串,需要進行下面的轉換;     1)把空格變成換行     2)添加注釋     比如你復制下來的公鑰是:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRBMjkaBznjXk06ddsL751KyYt   ztPFg0D3tu7jLqCacgqL+lbshIaItDGEXAMZmKa3DV6Wxy+l48YMo0RyS+dWze4M UmuxHU/v6tiT0ZTXJN3EwrjCtCyyttdv/ROB3CkheXnTKB76reTkQqg57OWW+m9j TCoccYMDXEIWYTs3CwIDAQAB,那轉換之後為:     -----BEGIN PUBLIC KEY-----   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRBMjkaBznjXk06ddsL751KyYt ztPFg0D3tu7jLqCacgqL+lbshIaItDGEXAMZmKa3DV6Wxy+l48YMo0RyS+dWze4M UmuxHU/v6tiT0ZTXJN3EwrjCtCyyttdv/ROB3CkheXnTKB76reTkQqg57OWW+m9j TCoccYMDXEIWYTs3CwIDAQAB -----END PUBLIC KEY-----     把公鑰保存在文件裡。    注意這個是2048位的公鑰應該是9行或者10行,不能為1行,不然PHP的openssl_pkey_get_public無法讀取,pub_key_id的結果為false,如果沒有-----BEGIN PUBLIC KEY----- 和 -----END PUBLIC KEY----- 可以自己加上,最後保存到一個rsa_public_key.pem文件中。   好了,現在已經有了所有的東西,先看簽名函數:   復制代碼  1 <?php  2 /**  3  * 簽名字符串  4  * @param $prestr 需要簽名的字符串  5  * return 簽名結果  6  */  7 function rsaSign($prestr) {  8     $public_key= file_get_contents('rsa_private_key.pem');  9     $pkeyid = openssl_get_privatekey($public_key); 10     openssl_sign($prestr, $sign, $pkeyid); 11     openssl_free_key($pkeyid); 12     $sign = base64_encode($sign); 13     return $sign; 14 } 15 ?> 復制代碼 注意點: 1.$prestr的內容和MD5一樣(參見手冊,但不包含最後的MD5密碼) 2.簽名用商戶私鑰 3.最後的簽名,需要用base64編碼 4.這個函數返回的值,就是這次請求的RSA簽名。   驗簽函數:   復制代碼  1 <?php  2 /**  3  * 驗證簽名  4  * @param $prestr 需要簽名的字符串  5  * @param $sign 簽名結果  6  * return 簽名結果  7  */  8 function rsaVerify($prestr, $sign) {  9     $sign = base64_decode($sign); 10     $public_key= file_get_contents('rsa_public_key.pem'); 11     $pkeyid = openssl_get_publickey($public_key); 12     if ($pkeyid) { 13         $verify = openssl_verify($prestr, $sign, $pkeyid); 14         openssl_free_key($pkeyid); 15     } 16     if($verify == 1){ 17         return true; 18     }else{ 19         return false; 20     } 21 } 22 ?> 復制代碼 注意點: 1.$prestr的內容和MD5一樣(參見手冊) 2.$sign是支付寶接口返回的sign參數用base64_decode解碼之後的二進制 3.驗簽用支付寶公鑰 4.這個函數返回一個布爾值,直接告訴你,驗簽是否通過     支付寶官方提供的PHP版SDK demo中只對MD5加密方式進行了處理,但android 端和ios端 請求支付寶加密方式只能用RSA加密算法,這時服務端PHP就無法驗證簽名了,所以需要對demo進行一些修改。   1、修改alipay_notify.class.php文件  verifyNotify 函數第46行  $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]);  改成 $isSign = $this->getSignVeryfy($_POST, $_POST["sign"], $_POST["sign_type"]);    verifyReturn 函數第83行 $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]);  改成  $isSign = $this->getSignVeryfy($_GET, $_GET["sign"], $_GET["sign_type"]);     getSignVeryfy 函數 116行 function getSignVeryfy($para_temp, $sign) { 改成 function getSignVeryfy($para_temp, $sign, $sign_type) {    getSignVeryfy 函數 127行 switch (strtoupper(trim($this->alipay_config['sign_type']))) {     case "MD5" :         $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']); break;     default :         $isSgin = false; }  改成 switch (strtoupper(trim($sign_type))) {     case "MD5" :         $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']); break;     case "RSA" :         $isSgin = rsaVerify($prestr, $sign);         break;      default :         $isSgin = false; }   2、新建一個alipay_rsa.function.php文件 復制代碼  1 <?php  2 /* *  3  * RSA  4  * 詳細:RSA加密  5  * 版本:3.3  6  * 日期:2014-02-20  7  * 說明:  8  * 以下代碼只是為了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。  9  * 該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。 10  */ 11 /** 12  * 簽名字符串 13  * @param $prestr 需要簽名的字符串 14  * return 簽名結果 15  */ 16 function rsaSign($prestr) { 17     $public_key= file_get_contents('rsa_private_key.pem'); 18     $pkeyid = openssl_get_privatekey($public_key); 19     openssl_sign($prestr, $sign, $pkeyid); 20     openssl_free_key($pkeyid); 21     $sign = base64_encode($sign); 22     return $sign; 23 } 24 /** 25  * 驗證簽名 26  * @param $prestr 需要簽名的字符串 27  * @param $sign 簽名結果 28  * return 簽名結果 29  */ 30 function rsaVerify($prestr, $sign) { 31     $sign = base64_decode($sign); 32     $public_key= file_get_contents('rsa_public_key.pem'); 33     $pkeyid = openssl_get_publickey($public_key); 34     if ($pkeyid) { 35         $verify = openssl_verify($prestr, $sign, $pkeyid); 36         openssl_free_key($pkeyid); 37     } 38     if($verify == 1){ 39         return true; 40     }else{ 41         return false; 42     } 43 } 44 ?> 復制代碼 最後要說的是官方提供的手冊上說的基本上都是正確的,只是有些地方沒有說的很詳細,開發的時候一定要多參考,大致就是這樣,祝大家好運。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved