123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- <?php
- class Wechatpay
- {
- const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';
- const AUTH_URL = '/token?grant_type=client_credential&';
- const API_BASE_URL_PREFIX = 'https://api.weixin.qq.com';
- const PAY_DELIVERNOTIFY = '/pay/delivernotify?';
- const PAY_ORDERQUERY = '/pay/orderquery?';
- private $appid;
- private $appsecret;
- private $access_token;
- private $user_token;
- private $partnerid;
- private $partnerkey;
- private $paysignkey;
- public $debug = false;
- public $errCode = 40001;
- public $errMsg = "no access";
- private $_logcallback;
- public function __construct($options)
- {
- $this->appid = isset($options['appid'])?$options['appid']:'';
- $this->appsecret = isset($options['appsecret'])?$options['appsecret']:'';
- $this->partnerid = isset($options['partnerid'])?$options['partnerid']:'';
- $this->partnerkey = isset($options['partnerkey'])?$options['partnerkey']:'';
- $this->paysignkey = isset($options['paysignkey'])?$options['paysignkey']:'';
- $this->debug = isset($options['debug'])?$options['debug']:false;
- $this->_logcallback = isset($options['logcallback'])?$options['logcallback']:false;
- }
- private function log($log){
- if ($this->debug && function_exists($this->_logcallback)) {
- if (is_array($log)) $log = print_r($log,true);
- return call_user_func($this->_logcallback,$log);
- }
- }
-
- private function http_get($url){
- $oCurl = curl_init();
- if(stripos($url,"https://")!==FALSE){
- curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
- curl_setopt($oCurl, CURLOPT_SSLVERSION, 1);
- }
- curl_setopt($oCurl, CURLOPT_URL, $url);
- curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
- $sContent = curl_exec($oCurl);
- $aStatus = curl_getinfo($oCurl);
- curl_close($oCurl);
- if(intval($aStatus["http_code"])==200){
- return $sContent;
- }else{
- return false;
- }
- }
-
- private function http_post($url,$param,$post_file=false){
- $oCurl = curl_init();
- if(stripos($url,"https://")!==FALSE){
- curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
- curl_setopt($oCurl, CURLOPT_SSLVERSION, 1);
- }
- if (is_string($param) || $post_file) {
- $strPOST = $param;
- } else {
- $aPOST = array();
- foreach($param as $key=>$val){
- $aPOST[] = $key."=".urlencode($val);
- }
- $strPOST = join("&", $aPOST);
- }
- curl_setopt($oCurl, CURLOPT_URL, $url);
- curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
- curl_setopt($oCurl, CURLOPT_POST,true);
- curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
- $sContent = curl_exec($oCurl);
- $aStatus = curl_getinfo($oCurl);
- curl_close($oCurl);
- if(intval($aStatus["http_code"])==200){
- return $sContent;
- }else{
- return false;
- }
- }
-
- public function checkAuth($appid='',$appsecret='',$token=''){
- if (!$appid || !$appsecret) {
- $appid = $this->appid;
- $appsecret = $this->appsecret;
- }
- if ($token) {
- $this->access_token=$token;
- return $this->access_token;
- }
-
- $result = $this->http_get(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$appid.'&secret='.$appsecret);
- if ($result)
- {
- $json = json_decode($result,true);
- if (!$json || isset($json['errcode'])) {
- $this->errCode = $json['errcode'];
- $this->errMsg = $json['errmsg'];
- return false;
- }
- $this->access_token = $json['access_token'];
- $expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600;
-
- return $this->access_token;
- }
- return false;
- }
-
- public function resetAuth($appid=''){
- if (!$appid) $appid = $this->appid;
- $this->access_token = '';
-
- return true;
- }
-
- static function json_encode($arr) {
- $parts = array ();
- $is_list = false;
-
- $keys = array_keys ( $arr );
- $max_length = count ( $arr ) - 1;
- if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) {
- $is_list = true;
- for($i = 0; $i < count ( $keys ); $i ++) {
- if ($i != $keys [$i]) {
- $is_list = false;
- break;
- }
- }
- }
- foreach ( $arr as $key => $value ) {
- if (is_array ( $value )) {
- if ($is_list)
- $parts [] = self::json_encode ( $value );
- else
- $parts [] = '"' . $key . '":' . self::json_encode ( $value );
- } else {
- $str = '';
- if (! $is_list)
- $str = '"' . $key . '":';
-
- if (!is_string ( $value ) && is_numeric ( $value ) && $value<2000000000)
- $str .= $value;
- elseif ($value === false)
- $str .= 'false';
- elseif ($value === true)
- $str .= 'true';
- else
- $str .= '"' . addslashes ( $value ) . '"';
-
- $parts [] = $str;
- }
- }
- $json = implode ( ',', $parts );
- if ($is_list)
- return '[' . $json . ']';
- return '{' . $json . '}';
- }
-
- public function getSignature($arrdata,$method="sha1") {
- if (!function_exists($method)) return false;
- ksort($arrdata);
- $paramstring = "";
- foreach($arrdata as $key => $value)
- {
- if(strlen($paramstring) == 0)
- $paramstring .= $key . "=" . $value;
- else
- $paramstring .= "&" . $key . "=" . $value;
- }
- $paySign = $method($paramstring);
- return $paySign;
- }
-
- public function generateNonceStr($length=16){
-
- $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- $str = "";
- for($i = 0; $i < $length; $i++)
- {
- $str .= $chars[mt_rand(0, strlen($chars) - 1)];
- }
- return $str;
- }
-
- public function createNativeUrl($productid){
- $nativeObj["appid"] = $this->appid;
- $nativeObj["appkey"] = $this->paysignkey;
- $nativeObj["productid"] = urlencode($productid);
- $nativeObj["timestamp"] = time();
- $nativeObj["noncestr"] = $this->generateNonceStr();
- $nativeObj["sign"] = $this->getSignature($nativeObj);
- unset($nativeObj["appkey"]);
- $bizString = "";
- foreach($nativeObj as $key => $value)
- {
- if(strlen($bizString) == 0)
- $bizString .= $key . "=" . $value;
- else
- $bizString .= "&" . $key . "=" . $value;
- }
- return "weixin://wxpay/bizpayurl?".$bizString;
-
- }
-
- public function createPackage($out_trade_no,$body,$total_fee,$notify_url,$spbill_create_ip,$fee_type=1,$bank_type="WX",$input_charset="UTF-8",$time_start="",$time_expire="",$transport_fee="",$product_fee="",$goods_tag="",$attach=""){
- $arrdata = array("bank_type" => $bank_type, "body" => $body, "partner" => $this->partnerid, "out_trade_no" => $out_trade_no, "total_fee" => $total_fee, "fee_type" => $fee_type, "notify_url" => $notify_url, "spbill_create_ip" => $spbill_create_ip, "input_charset" => $input_charset);
- if ($time_start) $arrdata['time_start'] = $time_start;
- if ($time_expire) $arrdata['time_expire'] = $time_expire;
- if ($transport_fee) $arrdata['transport_fee'] = $transport_fee;
- if ($product_fee) $arrdata['product_fee'] = $product_fee;
- if ($goods_tag) $arrdata['goods_tag'] = $goods_tag;
- if ($attach) $arrdata['attach'] = $attach;
- ksort($arrdata);
- $paramstring = "";
- foreach($arrdata as $key => $value)
- {
- if(strlen($paramstring) == 0)
- $paramstring .= $key . "=" . $value;
- else
- $paramstring .= "&" . $key . "=" . $value;
- }
- $stringSignTemp = $paramstring . "&key=" . $this->partnerkey;
- $signValue = strtoupper(md5($stringSignTemp));
- $package = http_build_query($arrdata) . "&sign=" . $signValue;
- return $package;
- }
-
- public function getPaySign($package, $timeStamp, $nonceStr){
- $arrdata = array("appid" => $this->appid, "timestamp" => $timeStamp, "noncestr" => $nonceStr, "package" => $package, "appkey" => $this->paysignkey);
- $paySign = $this->getSignature($arrdata);
- return $paySign;
- }
-
- public function checkOrderSignature($orderxml=''){
- if (!$orderxml) {
- $postStr = file_get_contents("php://input");
- if (!empty($postStr)) {
- $orderxml = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
- } else return false;
- }
- $arrdata = array('appid'=>$orderxml['AppId'],'appkey'=>$this->paysignkey,'timestamp'=>$orderxml['TimeStamp'],'noncestr'=>$orderxml['NonceStr'],'openid'=>$orderxml['OpenId'],'issubscribe'=>$orderxml['IsSubscribe']);
- $paySign = $this->getSignature($arrdata);
- if ($paySign!=$orderxml['AppSignature']) return false;
- return true;
- }
-
- public function sendPayDeliverNotify($openid,$transid,$out_trade_no,$status=1,$msg='ok'){
- if (!$this->access_token && !$this->checkAuth()) return false;
- $postdata = array(
- "appid"=>$this->appid,
- "appkey"=>$this->paysignkey,
- "openid"=>$openid,
- "transid"=>strval($transid),
- "out_trade_no"=>strval($out_trade_no),
- "deliver_timestamp"=>strval(time()),
- "deliver_status"=>strval($status),
- "deliver_msg"=>$msg,
- );
- $postdata['app_signature'] = $this->getSignature($postdata);
- $postdata['sign_method'] = 'sha1';
- unset($postdata['appkey']);
- $result = $this->http_post(self::API_BASE_URL_PREFIX.self::PAY_DELIVERNOTIFY.'access_token='.$this->access_token,self::json_encode($postdata));
- if ($result)
- {
- $json = json_decode($result,true);
- if (!$json || !empty($json['errcode'])) {
- $this->errCode = $json['errcode'];
- $this->errMsg = $json['errmsg'];
- return false;
- }
- return $json;
- }
- return false;
- }
-
- public function getPayOrder($out_trade_no) {
- if (!$this->access_token && !$this->checkAuth()) return false;
- $sign = strtoupper(md5("out_trade_no=$out_trade_no&partner={$this->partnerid}&key={$this->partnerkey}"));
- $postdata = array(
- "appid"=>$this->appid,
- "appkey"=>$this->paysignkey,
- "package"=>"out_trade_no=$out_trade_no&partner={$this->partnerid}&sign=$sign",
- "timestamp"=>strval(time()),
- );
- $postdata['app_signature'] = $this->getSignature($postdata);
- $postdata['sign_method'] = 'sha1';
- unset($postdata['appkey']);
- $result = $this->http_post(self::API_BASE_URL_PREFIX.self::PAY_ORDERQUERY.'access_token='.$this->access_token,self::json_encode($postdata));
- if ($result)
- {
- $json = json_decode($result,true);
- if (!$json || !empty($json['errcode'])) {
- $this->errCode = $json['errcode'];
- $this->errMsg = $json['errmsg'].json_encode($postdata);
- return false;
- }
- return $json["order_info"];
- }
- return false;
- }
-
- public function setUserToken($user_token) {
- return $this->user_token = $user_token;
- }
-
- public function getAddrSign($url, $timeStamp, $nonceStr, $user_token=''){
- if (!$user_token) $user_token = $this->user_token;
- if (!$user_token) {
- $this->errMsg = 'no user access token found!';
- return false;
- }
- $url = htmlspecialchars_decode($url);
- $arrdata = array(
- 'appid'=>$this->appid,
- 'url'=>$url,
- 'timestamp'=>strval($timeStamp),
- 'noncestr'=>$nonceStr,
- 'accesstoken'=>$user_token
- );
- return $this->getSignature($arrdata);
- }
- }
|