本文实例讲述了微信开放平台移动应用集成微信支付功能。分享给大家供大家参考。具体分析如下:
WechatAppPay文件代码如下:
<br /><?php<br />namespace common\services\WechatPay;<br />class WechatAppPay extends WechatPayBase<br />{<br /> //package参数<br /> public $package = [];<br /> //异步通知参数<br /> public $notify = [];<br /> //推送预支付订单参数<br /> protected $config = [];<br /> //存储access token和获取时间的文件<br /> protected $file;<br /> //access token<br /> protected $accessToken;<br /> //取access token的url<br /> const ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s';<br /> //生成预支付订单提交地址<br /> const POST_ORDER_URL = 'https://api.weixin.qq.com/pay/genprepay?access_token=%s';<br /> public function __construct()<br /> {<br /> $this->file = __DIR__ . '/payAccessToken.txt';<br /> }<br /> /**<br /> * 创建APP支付最终返回参数<br /> * @throws \Exception<br /> * @return multitype:string NULL<br /> */<br /> public function createAppPayData()<br /> {<br /> $this->generateConfig();<br /> $prepayid = $this->getPrepayid();<br /> try{<br /> $array = [<br /> 'appid' => $this->appid,<br /> 'appkey' => $this->paySignkey,<br /> 'noncestr' => $this->getRandomStr(),<br /> 'package' => 'Sign=WXPay',<br /> 'partnerid' => $this->partnerId,<br /> 'prepayid' => $prepayid,<br /> 'timestamp' => (string)time(),<br /> ];<br /> $array['sign'] = $this->sha1Sign($array);<br /> unset($array['appkey']);<br /> } catch(\Exception $e) {<br /> throw new \Exception($e->getMessage());<br /> }<br /> return $array;<br /> }<br /> /**<br /> * 验证支付成功后的通知参数<br /> * <br /> * @throws \Exception<br /> * @return boolean<br /> */<br /> public function verifyNotify()<br /> {<br /> try{<br /> $staySignStr = $this->notify;<br /> unset($staySignStr['sign']);<br /> $sign = $this->signData($staySignStr);<br /> return $this->notify['sign'] === $sign;<br /> } catch(\Exception $e) {<br /> throw new \Exception($e->getMessage());<br /> }<br /> }<br /> /**<br /> * 魔术方法,给添加支付参数进来<br /> * <br /> * @param string $name 参数名<br /> * @param string $value 参数值<br /> */<br /> public function __set($name, $value)<br /> {<br /> $this->$name = $value;<br /> }<br /> /**<br /> * 设置access token<br /> * @param string $token<br /> * @throws \Exception<br /> * @return boolean<br /> */<br /> public function setAccessToken()<br /> {<br /> try{<br /> if(!file_exists($this->file) || !is_file($this->file)) {<br /> $f = fopen($this->file, 'a');<br /> fclose($f);<br /> }<br /> $content = file_get_contents($this->file);<br /> if(!empty($content)) {<br /> $info = json_decode($content, true);<br /> if( time() - $info['getTime'] < 7150 ) {<br /> $this->accessToken = $info['accessToken'];<br /> return true<mark>@本文来源gaodaimacom搞#代%码@网-</mark><strong>搞代gaodaima码</strong>;<br /> }<br /> }<br /> //文件内容为空或access token已失效,重新获取<br /> $this->outputAccessTokenToFile();<br /> } catch(\Exception $e) {<br /> throw new \Exception($e->getMessage());<br /> }<br /> return true;<br /> }<br /> /**<br /> * 写入access token 到文件<br /> * @throws \Exception<br /> * @return boolean<br /> */<br /> protected function outputAccessTokenToFile()<br /> {<br /> try{<br /> $f = fopen($this->file, 'wb');<br /> $token = [<br /> 'accessToken' => $this->getAccessToken(),<br /> 'getTime' => time(),<br /> ];<br /> flock($f, LOCK_EX);<br /> fwrite($f, json_encode($token));<br /> flock($f, LOCK_UN);<br /> fclose($f);<br /> $this->accessToken = $token['accessToken'];<br /> } catch(\Exception $e) {<br /> throw new \Exception($e->getMessage());<br /> }<br /> return true;<br /> }<br /> /**<br /> * 取access token<br /> * <br /> * @throws \Exception<br /> * @return string<br /> */<br /> protected function getAccessToken()<br /> {<br /> $url = sprintf(self::ACCESS_TOKEN_URL, $this->appid, $this->appSecret);<br /> $result = json_decode( $this->getUrl($url), true );<br /> if(isset($result['errcode'])) {<br /> throw new \Exception("get access token failed:{$result['errmsg']}");<br /> }<br /> return $result['access_token'];<br /> }<br /> /**<br /> * 取预支付会话标识<br /> * <br /> * @throws \Exception<br /> * @return string<br /> */<br /> protected function getPrepayid()<br /> {<br /> $data = json_encode($this->config);<br /> $url = sprintf(self::POST_ORDER_URL, $this->accessToken);<br /> $result = json_decode( $this->postUrl($url, $data), true );<br /> if( isset($result['errcode']) && $result['errcode'] != 0 ) {<br /> throw new \Exception($result['errmsg']);<br /> }<br /> if( !isset($result['prepayid']) ) {<br /> throw new \Exception('get prepayid failed, url request error.');<br /> }<br /> return $result['prepayid'];<br /> }<br /> /**<br /> * 组装预支付参数<br /> * <br /> * @throws \Exception<br /> */<br /> protected function generateConfig()<br /> {<br /> try{<br /> $this->config = [<br /> 'appid' => $this->appid,<br /> 'traceid' => $this->traceid,<br /> 'noncestr' => $this->getRandomStr(),<br /> 'timestamp' => time(),<br /> 'package' => $this->generatePackage(),<br /> 'sign_method' => $this->sign_method,<br /> ];<br /> $this->config['app_signature'] = $this->generateSign();<br /> } catch(\Exception $e) {<br /> throw new \Exception($e->getMessage());<br /> }<br /> }<br /> /**<br /> * 生成package字段<br /> * <br /> * 生成规则:<br /> * 1、生成sign的值signValue<br /> * 2、对package参数再次拼接成查询字符串,值需要进行urlencode<br /> * 3、将sign=signValue拼接到2生成的字符串后面得到最终的package字符串<br /> * <br /> * 第2步urlencode空格需要编码成%20而不是+<br /> * <br /> * RFC 1738会把 空格编码成+<br /> * RFC 3986会把空格编码成%20<br /> * <br /> * @return string<br /> */<br /> protected function generatePackage()<br /> {<br /> $this->package['sign'] = $this->signData($this->package);<br /> return http_build_query($this->package, '', '&', PHP_QUERY_RFC3986);<br /> }<br /> /**<br /> * 生成签名<br /> * <br /> * @return string<br /> */<br /> protected function generateSign()<br /> {<br /> $signArray = [<br /> 'appid' => $this->appid,<br /> 'appkey' => $this->paySignkey,<br /> 'noncestr' => $this->config['noncestr'],<br /> 'package' => $this->config['package'],<br /> 'timestamp' => $this->config['timestamp'],<br /> 'traceid' => $this->traceid,<br /> ];<br /> return $this->sha1Sign($signArray);<br /> }<br /> /**<br /> * 签名数据<br /> * <br /> * 生成规则:<br /> * 1、字典排序,拼接成查询字符串格式,不需要urlencode<br /> * 2、上一步得到的字符串最后拼接上key=paternerKey<br /> * 3、MD5哈希字符串并转换成大写得到sign的值signValue<br /> * <br /> * @param array $data 待签名数据<br /> * @return string 最终签名结果<br /> */<br /> protected function signData($data)<br /> {<br /> ksort($data);<br /> $str = $this->arrayToString($data);<br /> $str .= "&key={$this->partnerKey}";<br /> return strtoupper( $this->signMd5($str) );<br /> }<br /> /**<br /> * sha1签名<br /> * 签名规则<br /> * 1、字典排序<br /> * 2、拼接查询字符串<br /> * 3、sha1运算<br /> * <br /> * @param array $arr<br /> * @return string<br /> */<br /> protected function sha1Sign($arr)<br /> {<br /> ksort($arr);<br /> return sha1( $this->arrayToString($arr) );<br /> }<br />}<br />
希望本文所述对大家的php程序设计有所帮助。