关于微信支付

前一段时间做了微信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的框架,因为之前公众号支付已经做好了,所以在微信配置、申请方面 有的已经忘了,所以就不乱说了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值