小程序与php 实现微信支付

小程序访问地址:

paytest.php:

include 'WeixinPay.php';           //微信统一下单、加密等函数类文件
$appid='';          //小程序appid
$openid= 'oluqV5PKJzE8KVC5ky_iylTOnAY4';          //用户的微信openid
$mch_id='';              //微信商户号
$key='';          //微信支付API密钥
$out_trade_no = $mch_id. time();              //订单号
$total_fee = 0.01;  
if(empty($total_fee)) //押金  
{  
    $body = "充值押金";  
    $total_fee = floatval(99*100);  
}  
 else {  
     $body = "充值余额";  
     $total_fee = floatval($total_fee*100);  
 }  
$weixinpay = new WeixinPay($appid,$openid,$mch_id,$key,$out_trade_no,$body,$total_fee);  
$return=$weixinpay->pay();  
  
echo json_encode($return);  
?>

WeixinPay.php:

/* 
 * 小程序微信支付 
 */  
  
class WeixinPay {  
    protected $appid;  
    protected $mch_id;  
    protected $key;  
    protected $openid;  
    protected $out_trade_no;  
    protected $body;  
    protected $total_fee;  
protected $nonce_str;

function __construct($appid, $openid, $mch_id, $key,$out_trade_no,$body,$total_fee) {  
        $this->appid = $appid;  
        $this->openid = $openid;  
        $this->mch_id = $mch_id;  
        $this->key = $key;  
        $this->out_trade_no = $out_trade_no;  
        $this->body = $body;  
        $this->total_fee = $total_fee;  
$this->nonce_str = $this->createNoncestr();  
    }  
  
  
    public function pay() {  
        //统一下单接口  
        $return = $this->weixinapp();  
        return $return;  
    }  
  
  
    //统一下单接口  
    private function unifiedorder() {  
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';  
        $parameters = array(  
            'appid' => $this->appid, //小程序ID  
            'mch_id' => $this->mch_id, //商户号  
            'nonce_str' => $this->nonce_str, //随机字符串  
//            'body' => 'test', //商品描述  
            'body' => $this->body,  
//            'out_trade_no' => '2015450806125348', //商户订单号  
            'out_trade_no'=> $this->out_trade_no,  
//            'total_fee' => floatval(0.01 * 100), //总金额 单位 分  
            'total_fee' => $this->total_fee,  
//            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP  
            'spbill_create_ip' => '127.0.0.1', //终端IP  
            'notify_url' => 'http://你的域名/notify.php', //异步通知地址  确保外网能正常访问  
            'openid' => $this->openid, //用户id  
            'trade_type' => 'JSAPI'//交易类型  
        );  
        //统一下单签名  
        $parameters['sign'] = $this->getSign($parameters);  
        $xmlData = $this->arrayToXml($parameters);  
        $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));  
        return $return;  
    }  
  
  
    private static function postXmlCurl($xml, $url, $second = 30)   
    {  
        $ch = curl_init();  
        //设置超时  
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);  
        curl_setopt($ch, CURLOPT_URL, $url);  
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);  
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验  
        //设置header  
        curl_setopt($ch, CURLOPT_HEADER, FALSE);  
        //要求结果为字符串且输出到屏幕上  
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);  
        //post提交方式  
        curl_setopt($ch, CURLOPT_POST, TRUE);  
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);  
  
  
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);  
        curl_setopt($ch, CURLOPT_TIMEOUT, 40);  
        set_time_limit(0);  
  
  
        //运行curl  
        $data = curl_exec($ch);  
        //返回结果  
        if ($data) {  
            curl_close($ch);  
            return $data;  
        } else {  
            $error = curl_errno($ch);  
            curl_close($ch);  
            throw new WxPayException("curl出错,错误码:$error");  
        }  
    }  
      
      
      
    //数组转换成xml  
    private function arrayToXml($arr) {  
        $xml = "";  
        foreach ($arr as $key => $val) {  
            if (is_array($val)) {  
                $xml .= "<" . $key . ">" . arrayToXml($val) . "";  
            } else {  
                $xml .= "<" . $key . ">" . $val . "";  
            }  
        }  
        $xml .= "
";  
        return $xml;  
    }  
  
  
    //xml转换成数组  
    private function xmlToArray($xml) {  
  
  
        //禁止引用外部xml实体   
  
  
        libxml_disable_entity_loader(true);  
  
  
        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);  
  
  
        $val = json_decode(json_encode($xmlstring), true);  
  
  
        return $val;  
    }  
  
  
    //微信小程序接口  
    private function weixinapp() {  
        //统一下单接口  
        $unifiedorder = $this->unifiedorder();  
//        print_r($unifiedorder);  
        $parameters = array(  
            'appId' => $this->appid, //小程序ID  
            'timeStamp' => '' . time() . '', //时间戳  
            'nonceStr' => $this->nonce_str, //随机串  
            'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包  
            'signType' => 'MD5'//签名方式  
        );  
        //签名  
        $parameters['paySign'] = $this->getSign($parameters);  
        return $parameters;  
    }  
  
  
    //作用:产生随机字符串,不长于32位  
    private function createNoncestr($length = 32) {  
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
        $str = "";  
        for ($i = 0; $i < $length; $i++) {  
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);  
        }  
        return $str;  
    }  
  
  
    //作用:生成签名  
    private function getSign($Obj) {  
        foreach ($Obj as $k => $v) {  
            $Parameters[$k] = $v;  
        }  
        //签名步骤一:按字典序排序参数  
        ksort($Parameters);  
        $String = $this->formatBizQueryParaMap($Parameters, false);  
        //签名步骤二:在string后加入KEY  
        $String = $String . "&key=" . $this->key;  
        //签名步骤三:MD5加密  
        $String = md5($String);  
        //签名步骤四:所有字符转为大写  
        $result_ = strtoupper($String);  
        return $result_;  
    }  
  
  
    ///作用:格式化参数,签名过程需要使用  
    private function formatBizQueryParaMap($paraMap, $urlencode) {  
        $buff = "";  
        ksort($paraMap);  
        foreach ($paraMap as $k => $v) {  
            if ($urlencode) {  
                $v = urlencode($v);  
            }  
            $buff .= $k . "=" . $v . "&";  
        }  
        $reqPar;  
        if (strlen($buff) > 0) {  
            $reqPar = substr($buff, 0, strlen($buff) - 1);  
        }  
        return $reqPar;  
    }  
  
  
}  

notify.php:

include_once("./log_.php");


date_default_timezone_set('prc');


//微信支付回调验证  
//$xml = $GLOBALS['HTTP_RAW_POST_DATA'];        //PHP7以下版本使用这个获取(如果不能获取,使用下面这行)
$xml = file_get_contents("php://input");      //使用的是php7,原因是php7已移除这个全局变量

//以log文件形式记录回调信息
$log_ = new Log_();
$log_name="./notify_url.log";//log文件路径
$log_->log_result($log_name,"test Acepe\n".$xml."\n");
 
//将服务器返回的XML数据转化为数组  
$data = self::xml2array($xml);  
// 保存微信服务器返回的签名sign  
$data_sign = $data['sign'];  
// sign不参与签名算法  
unset($data['sign']);  
$sign = self::makeSign($data);  
  
// 判断签名是否正确  判断支付状态  
if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {  
$result = $data;  
//获取服务器返回的数据  
$order_sn = $data['out_trade_no'];          //订单单号  
$openid = $data['openid'];                  //付款人openID  
$total_fee = $data['total_fee'];            //付款金额  
$transaction_id = $data['transaction_id'];  //微信支付流水号  
 
//更新数据库  
$this->updateDB($order_sn,$openid,$total_fee,$transaction_id);  
 
}else{  
$result = false;  
}  
// 返回状态给微信服务器  
if ($result) {  
$str='';  
}else{  
$str='';  
}  
echo $str;  
return $result;  


?>


log_.php:



class Log_
{
// 打印log
function  log_result($file,$word) 
{
   $fp = fopen($file,"a");
   flock($fp, LOCK_EX) ;
   fwrite($fp,"执行日期:".date("Y-m-d H:i:s",time())."\n".$word."\n\n");
   flock($fp, LOCK_UN);
   fclose($fp);
}
}

?>

你可能感兴趣的:(thinkphp)