关于微信支付

来源:互联网 发布:java web开发与实战 编辑:程序博客网 时间:2024/05/29 08:48

前一段时间做了微信APP支付。直接贴代码

APP端访问这个接口,然后可以(APP端也需要处理)唤起微信

public function pay(){         $Wxpay = new \Wxpay();        $Wxpay->total_fee = intval(1 * 100);//订单的金额 1          $Wxpay->out_trade_no = date('YmdHis') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));//订单号;        $Wxpay->body = '充值费用';//支付描述信息         $Wxpay->time_expire = date('YmdHis', time() + 86400);//订单支付的过期时间(eg:一天过期)        $Wxpay->notify_url = '异步的地址';//异步通知URL(更改支付状态)        //数据以JSON的形式返回给APP        $app_response = $Wxpay->doPay();        // 添加订单           if (isset($app_response['return_code']) && $app_response['return_code'] == 'FAIL'){               $errorCode = 100;               $errorMsg = $app_response['return_msg'];               self::echoResult($errorCode, $errorMsg);           } else {               $errorCode = 0;               $errorMsg = 'success';               $responseData = array(                  'notify_url' => $Wxpay->notify_url,                  'app_response' => $app_response,               );              self::echoResult($errorCode, $errorMsg, $responseData);           }   }  //接口输出   public function echoResult($errorCode = 0, $errorMsg = 'success', $responseData = array())    {        $arr = array(            'errorCode' => $errorCode,            'errorMsg' => $errorMsg,            'responseData' => $responseData,        );        exit(json_encode($arr));    }
当支付成功时的异步通知(确认是否支付)

      // 微信异步通知页面,课时支付    public function notify(){        $Wxpay = new \Wxpay();        $verify_result = $Wxpay->verifyNotify();        if (isset($verify_result['result_code']) && $verify_result['result_code']=='SUCCESS') {          $requestReturnData = file_get_contents("php://input");          $out_trade_no = $verify_result['out_trade_no'];             //商户订单号            $trade_no     = $verify_result['transaction_id'];           //交易号            $trade_status = $verify_result['result_code'];              //交易状态            $total_fee    = $verify_result['total_fee']/100;            //支付金额            $pay_date     = $verify_result['time_end'];                 //支付过期时间            $pay_ip       = $verify_result['attach'];                   //IP            /*                @todo                1.更改订单状态为已支付。(需自己完善)                2.添加付款信息到数据库,方便对账。(需自己完善)            */            //处理后同步返回给微信            exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');        }    exit('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>');}微信APP支付类
<?php/** * @desc 微信APP支付类 * @author shangheguang@yeah.net * @date 2015-08-24 */class Wxpay {      //参数配置   public $config;      //服务器异步通知页面路径(必填)   public $notify_url = '';      //商户订单号(必填,商户网站订单系统中唯一订单号)   public $out_trade_no = '';   //商品描述(必填,不填则为商品名称)   public $body = '';      //付款金额(必填)   public $total_fee = 0;      //自定义超时(选填,支持dhmc)   public $time_expire = '';      private $WxPayHelper;      function __construct()    {      $config = C('wxconfig');      $this->config         = $config;      $this->WxPayHelper = new WxPayHelper();   }      public function chkParam()    {      //用户网站订单号      if (empty($this->out_trade_no)) {         die('out_trade_no error');      }        //商品描述      if (empty($this->body)) {         die('body error');      }      if (empty($this->time_expire)){         die('time_expire error');      }      //检测支付金额      if (empty($this->total_fee) || !is_numeric($this->total_fee)) {         die('total_fee error');      }      //异步通知URL      if (empty($this->notify_url)) {         die('notify_url error');      }      if (!preg_match("#^http:\/\/#i", $this->notify_url)) {         $this->notify_url = "http://" . $_SERVER['HTTP_HOST'] . $this->notify_url;      }      return true;   }      /**    * 生成支付(返回给APP)    * @return boolean|mixed    */   public function doPay() {       //检测构造参数       $this->chkParam();       return $this->createAppPara();   }       /**     * APP统一下单     */   private  function createAppPara()    {      $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";              $data["appid"]          = $this->config['appid'];//微信开放平台审核通过的应用APPID        $data["body"]       = $this->body;//商品或支付单简要描述        $data["mch_id"]      = $this->config['mch_id'];//商户号        $data["nonce_str"]       = $this->WxPayHelper->getRandChar(32);//随机字符串        $data["notify_url"]   = $this->notify_url;//通知地址        $data["out_trade_no"] = $this->out_trade_no;//商户订单号        $data["spbill_create_ip"] = $this->WxPayHelper->get_client_ip();//终端IP        $data["total_fee"]        = $this->total_fee;//总金额        $data["time_expire"]     = $this->time_expire;//交易结束时间        $data["trade_type"]      = "APP";//交易类型        $data["sign"]          = $this->WxPayHelper->getSign($data, $this->config['api_key']);//签名        $xml      = $this->WxPayHelper->arrayToXml($data);        $response  = $this->WxPayHelper->postXmlCurl($xml, $url);        //将微信返回的结果xml转成数组        $responseArr = $this->WxPayHelper->xmlToArray($response);        if(isset($responseArr["return_code"]) && $responseArr["return_code"]=='SUCCESS'){           return     $this->getOrder($responseArr['prepay_id']);        }        return $responseArr;   }      /**    * 执行第二次签名,才能返回给客户端使用    * @param int $prepayId:预支付交易会话标识    * @return array    */   public function getOrder($prepayId)   {      $data["appid"]        = $this->config['appid'];      $data["noncestr"]  = $this->WxPayHelper->getRandChar(32);      $data["package"]   = "Sign=WXPay";      $data["partnerid"]     = $this->config['mch_id'];      $data["prepayid"]  = $prepayId;      $data["timestamp"]     = time();      $data["sign"]     = $this->WxPayHelper->getSign($data, $this->config['api_key']);      $data["packagestr"] = "Sign=WXPay";      return $data;   }      /**    * 异步通知信息验证    * @return boolean|mixed    */   public function verifyNotify()   {      $xml = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';      if(!$xml){         return false;      }      $wx_back = $this->WxPayHelper->xmlToArray($xml);      if(empty($wx_back)){         return false;      }      $checkSign = $this->WxPayHelper->getVerifySign($wx_back, $this->config['api_key']);             if($checkSign==$wx_back['sign']){         return $wx_back;      }  return false;   }      function __destruct() {         }   /**    * 验证签名    * @param array $data    * @param string $key    * @return string    */   function getVerifySign($data, $key)   {      $String = $this->formatParameters($data, false);      //签名步骤二:在string后加入KEY      $String = $String . "&key=" . $key;      //签名步骤三:MD5加密      $String = md5($String);      //签名步骤四:所有字符转为大写      $result = strtoupper($String);      return $result;   }   function formatParameters($paraMap, $urlencode)   {      $buff = "";      ksort($paraMap);      foreach ($paraMap as $k => $v) {         if($k=="sign"){            continue;         }         if ($urlencode) {            $v = urlencode($v);         }         $buff .= $k . "=" . $v . "&";      }      $reqPar;      if (strlen($buff) > 0) {         $reqPar = substr($buff, 0, strlen($buff) - 1);      }      return $reqPar;   }}

<?php
WxPayHelper类

 class WxPayHelper{ /** * 验证签名 * @param array $data * @param string $key * @return string */ function getVerifySign($data, $key) { $String = $this->formatParameters($data, false); //签名步骤二:在string后加入KEY $String = $String . "&key=" . $key; //签名步骤三:MD5加密 $String = md5($String); //签名步骤四:所有字符转为大写 $result = strtoupper($String); return $result; } function formatParameters($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($k=="sign"){ continue; } if ($urlencode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff) - 1); } return $reqPar; } /** * 得到签名 * @param object $obj * @param string $api_key * @return string */ function getSign($obj, $api_key) { foreach ($obj as $k => $v) { $Parameters[strtolower($k)] = $v; } //签名步骤一:按字典序排序参数 ksort($Parameters); $String = $this->formatBizQueryParaMap($Parameters, false); //签名步骤二:在string后加入KEY $String = $String."&key=".$api_key; //签名步骤三:MD5加密 $result = strtoupper(md5($String)); return $result; } /** * 获取指定长度的随机字符串 * @param int $length * @return Ambigous <NULL, string> */ function getRandChar($length){ $str = null; $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; $max = strlen($strPol)-1; for($i=0;$i<$length;$i++){ $str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于minmax两个数之间的一个随机整数 } return $str; } /** * 数组转xml * @param array $arr * @return string */ function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key=>$val) { if (is_numeric($val)) { $xml.="<".$key.">".$val."</".$key.">"; } else $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } $xml.="</xml>"; return $xml; } /** * post方式提交xml到对应的接口url * * @param string $xml 需要postxml数据 * @param string $url url * @param bool $useCert 是否需要证书,默认不需要 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ function postXmlCurl($xml, $url, $second=30, $useCert=false, $sslcert_path='', $sslkey_path='') { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch,CURLOPT_URL, $url); //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); if($useCert == true){ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验 //设置证书 //使用证书:cert key 分别属于两个.pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLCERT, $sslcert_path); curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); curl_setopt($ch,CURLOPT_SSLKEY, $sslkey_path); } //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //运行curl $data = curl_exec($ch); //返回结果 if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return false; } } /** * 获取当前服务器的IP * @return Ambigous <string, unknown> */ function get_client_ip() { if (isset($_SERVER['REMOTE_ADDR'])) { $cip = $_SERVER['REMOTE_ADDR']; } elseif (getenv("REMOTE_ADDR")) { $cip = getenv("REMOTE_ADDR"); } elseif (getenv("HTTP_CLIENT_IP")) { $cip = getenv("HTTP_CLIENT_IP"); } else { $cip = "127.0.0.1"; } return $cip; } /** * 将数组转成uri字符串 * @param array $paraMap * @param bool $urlencode * @return string */ function formatBizQueryParaMap($paraMap, $urlencode) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if($urlencode) { $v = urlencode($v); } $buff .= strtolower($k) . "=" . $v . "&"; } $reqPar; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff)-1); } return $reqPar; } /** * XML转数组 * @param unknown $xml * @return mixed */ function xmlToArray($xml) { //XML转为array $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $array_data; }}
配置文件
'wxconfig' => array(    'appid' => "wxxxxxxxxxxxxxxxxx",                  /*微信开放平台上的应用id*/    'mch_id' => "xxxxxxxxxx",                         /*微信申请成功之后邮件中的商户id*/    'api_key' => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",    /*在微信商户平台上自己设定的api密钥 32*/)
我使用的是thinkphp的框架,因为之前公众号支付已经做好了,所以在微信配置、申请方面 有的已经忘了,所以就不乱说了


原创粉丝点击