php微信支付之APP支付方法

php微信支付之APP支付方法
  本文實例講述了微信開放平臺移動應用集成微信支付功能。分享給大家供大家參考。具體分析如下,更多消息請關注應屆畢業生網!  WechatAppPay文件代碼如下:  ?  <?php  namespace commonservicesWechatPay;  class WechatAppPay extends WechatPayBase  {  //package參數  public $package = [];  //異步通知參數  public $notify = [];  //推送預支付訂單參數  protected $config = [];  //存儲access token和獲取時間的文件  protected $file;  //access token  protected $accessToken;  //取access token的url  const ACCESS_TOKEN_URL = '_type=client_credential&appid=%s&secret=%s';  //生成預支付訂單提交地址  const POST_ORDER_URL = '_token=%s';  public function __construct()  {  $this->file = __DIR__ . '/';  }  /**  * 創建APP支付最終返回參數  * @throws Exception  * @return multitype:string NULL  */  public function createAppPayData()  {  $this->generateConfig();  $prepayid = $this->getPrepayid();  try{  $array = [  'appid' => $this->appid,  'appkey' => $this->paySignkey,  'noncestr' => $this->getRandomStr(),  'package' => 'Sign=WXPay',  'partnerid' => $this->partnerId,  'prepayid' => $prepayid,  'timestamp' => (string)time(),  ];  $array['sign'] = $this->sha1Sign($array);  unset($array['appkey']);  } catch(Exception $e) {  throw new Exception($e->getMessage());  }  return $array;  }  /**  * 驗證支付成功後的.通知參數  *  * @throws Exception  * @return boolean  */  public function verifyNotify()  {  try{  $staySignStr = $this->notify;  unset($staySignStr['sign']);  $sign = $this->signData($staySignStr);  return $this->notify['sign'] === $sign;  } catch(Exception $e) {  throw new Exception($e->getMessage());  }  }  /**  * 魔術方法,給添加支付參數進來  *  * @param string $name 參數名  * @param string $value 參數值  */  public function __set($name, $value)  {  $this->$name = $value;  }  /**  * 設置access token  * @param string $token  * @throws Exception  * @return boolean  */  public function setAccessToken()  {  try{  if(!file_exists($this->file) || !is_file($this->file)) {  $f = fopen($this->file, 'a');  fclose($f);  }  $content = file_get_contents($this->file);  if(!empty($content)) {  $info = json_decode($content, true);  if( time() - $info['getTime'] < 7150 ) {  $this->accessToken = $info['accessToken'];  return true;  }  }  //文件內容爲空或access token已失效,重新獲取  $this->outputAccessTokenToFile();  } catch(Exception $e) {  throw new Exception($e->getMessage());  }  return true;  }  /**  * 寫入access token 到文件  * @throws Exception  * @return boolean  */  protected function outputAccessTokenToFile()  {  try{  $f = fopen($this->file, 'wb');  $token = [  'accessToken' => $this->getAccessToken(),  'getTime' => time(),  ];  flock($f, LOCK_EX);  fwrite($f, json_encode($token));  flock($f, LOCK_UN);  fclose($f);  $this->accessToken = $token['accessToken'];  } catch(Exception $e) {  throw new Exception($e->getMessage());  }  return true;  }  /**  * 取access token  *  * @throws Exception  * @return string  */  protected function getAccessToken()  {  $url = sprintf(self::ACCESS_TOKEN_URL, $this->appid, $this->appSecret);  $result = json_decode( $this->getUrl($url), true );  if(isset($result['errcode'])) {  throw new Exception("get access token failed:{$result['errmsg']}");  }  return $result['access_token'];  }  /**  * 取預支付會話標識  *  * @throws Exception  * @return string  */  protected function getPrepayid()  {  $data = json_encode($this->config);  $url = sprintf(self::POST_ORDER_URL, $this->accessToken);  $result = json_decode( $this->postUrl($url, $data), true );  if( isset($result['errcode']) && $result['errcode'] != 0 ) {  throw new Exception($result['errmsg']);  }  if( !isset($result['prepayid']) ) {  throw new Exception('get prepayid failed, url request error.');  }  return $result['prepayid'];  }  /**  * 組裝預支付參數  *  * @throws Exception  */  protected function generateConfig()  {  try{  $this->config = [  'appid' => $this->appid,  'traceid' => $this->traceid,  'noncestr' => $this->getRandomStr(),  'timestamp' => time(),  'package' => $this->generatePackage(),  'sign_method' => $this->sign_method,  ];  $this->config['app_signature'] = $this->generateSign();  } catch(Exception $e) {  throw new Exception($e->getMessage());  }  }  /**  * 生成package字段  *  * 生成規則:  * 1、生成sign的值signValue  * 2、對package參數再次拼接成查詢字符串,值需要進行urlencode  * 3、將sign=signValue拼接到2生成的字符串後面得到最終的package字符串  *  * 第2步urlencode空格需要編碼成%20而不是+  *  * RFC 1738會把 空格編碼成+  * RFC 3986會把空格編碼成%20  *  * @return string  */  protected function generatePackage()  {  $this->package['sign'] = $this->signData($this->package);  return http_build_query($this->package, '', '&', PHP_QUERY_RFC3986);  }  /**  * 生成簽名  *  * @return string  */  protected function generateSign()  {  $signArray = [  'appid' => $this->appid,  'appkey' => $this->paySignkey,  'noncestr' => $this->config['noncestr'],  'package' => $this->config['package'],  'timestamp' => $this->config['timestamp'],  'traceid' => $this->traceid,  ];  return $this->sha1Sign($signArray);  }  /**  * 簽名數據  *  * 生成規則:  * 1、字典排序,拼接成查詢字符串格式,不需要urlencode  * 2、上一步得到的字符串最後拼接上key=paternerKey  * 3、MD5哈希字符串並轉換成大寫得到sign的值signValue  *  * @param array $data 待簽名數據  * @return string 最終簽名結果  */  protected function signData($data)  {  ksort($data);  $str = $this->arrayToString($data);  $str .= "&key={$this->partnerKey}";  return strtoupper( $this->signMd5($str) );  }  /**  * sha1簽名  * 簽名規則  * 1、字典排序  * 2、拼接查詢字符串  * 3、sha1運算  *  * @param array $arr  * @return string  */  protected function sha1Sign($arr)  {  ksort($arr);  return sha1( $this->arrayToString($arr) );  }  }  希望本文所述對大家的php程序設計有所幫助。