当前位置:首页 > PHP教程 > php高级应用 > 列表

php实现微信原生支付(扫码支付)功能

发布:smiling 来源: PHP粉丝网  添加日期:2021-09-20 16:03:38 浏览: 评论:0 

网上的很多PHP微信扫码支付接入教程都颇为复杂,且需要配置和引入较多的文件,本人通过整理后给出一个单文件版的,只有200行代码,希望可以给各位想接入微信扫码支付的带来些许帮助和借鉴意义。

直接运行该文件即可得到一个支付二维码的图片。

需要注意的事项:

1.该文件需放到支付授权目录下,可以在微信支付商户平台->产品中心->开发配置中设置。

2.如提示签名错误可以通过微信支付签名验证工具进行验证:微信公众平台支付接口调试工具

代码如下:

  1. <?php 
  2. header('Content-type:text/html; Charset=utf-8'); 
  3. $mchid = 'xxxxx';     //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送 
  4. $appid = 'xxxxx'; //公众号APPID 通过微信支付商户资料审核后邮件发送 
  5. $apiKey = 'xxxxx';  //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 
  6. $wxPay = new WxpayService($mchid,$appid,$apiKey); 
  7. $outTradeNo = uniqid();   //你自己的商品订单号 
  8. $payAmount = 0.01;     //付款金额,单位:元 
  9. $orderName = '支付测试';  //订单标题 
  10. $notifyUrl = 'https://www.xxx.com/wx/';   //付款成功后的回调地址(不要有问号) 
  11. $payTime = time();   //付款时间 
  12. $arr = $wxPay->createJsBizPackage($payAmount,$outTradeNo,$orderName,$notifyUrl,$payTime); 
  13. //生成二维码 
  14. $url = 'http://qr.liantu.com/api.php?text='.$arr['code_url']; 
  15. echo "<img src='{$url}' style='width:300px;'>"; 
  16.  
  17. class WxpayService 
  18. { 
  19.   protected $mchid; 
  20.   protected $appid; 
  21.   protected $apiKey; 
  22.  
  23.   public function __construct($mchid, $appid, $key) 
  24.   { 
  25.     $this->mchid = $mchid; 
  26.     $this->appid = $appid; 
  27.     $this->apiKey = $key; 
  28.   } 
  29.  
  30.   /** 
  31.    * 发起订单 
  32.    * @param float $totalFee 收款总费用 单位元 
  33.    * @param string $outTradeNo 唯一的订单号 
  34.    * @param string $orderName 订单名称 
  35.    * @param string $notifyUrl 支付结果通知url 不要有问号 
  36.    * @param string $timestamp 订单发起时间 
  37.    * @return array 
  38.    */ 
  39.   public function createJsBizPackage($totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp) 
  40.   { 
  41.     $config = array( 
  42.       'mch_id' => $this->mchid, 
  43.       'appid' => $this->appid, 
  44.       'key' => $this->apiKey, 
  45.     ); 
  46.     $orderName = iconv('GBK','UTF-8',$orderName); 
  47.     $unified = array( 
  48.       'appid' => $config['appid'], 
  49.       'attach' => 'pay',       //商家数据包,原样返回,如果填写中文,请注意转换为utf-8 
  50.       'body' => $orderName, 
  51.       'mch_id' => $config['mch_id'], 
  52.       'nonce_str' => self::createNonceStr(), 
  53.       'notify_url' => $notifyUrl, 
  54.       'out_trade_no' => $outTradeNo, 
  55.       'spbill_create_ip' => '127.0.0.1', 
  56.       'total_fee' => intval($totalFee * 100),    //单位 转为分 
  57.       'trade_type' => 'NATIVE', 
  58.     ); 
  59.     $unified['sign'] = self::getSign($unified, $config['key']); 
  60.     $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified)); 
  61.     $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA); 
  62.     if ($unifiedOrder === false) { 
  63.       die('parse xml error'); 
  64.     } 
  65.     if ($unifiedOrder->return_code != 'SUCCESS') { 
  66.       die($unifiedOrder->return_msg); 
  67.     } 
  68.     if ($unifiedOrder->result_code != 'SUCCESS') { 
  69.       die($unifiedOrder->err_code); 
  70.     } 
  71.     $codeUrl = (array)($unifiedOrder->code_url); 
  72.     if(!$codeUrl[0]) exit('get code_url error'); 
  73.     $arr = array( 
  74.       "appId" => $config['appid'], 
  75.       "timeStamp" => $timestamp, 
  76.       "nonceStr" => self::createNonceStr(), 
  77.       "package" => "prepay_id=" . $unifiedOrder->prepay_id, 
  78.       "signType" => 'MD5', 
  79.       "code_url" => $codeUrl[0], 
  80.     ); 
  81.     $arr['paySign'] = self::getSign($arr, $config['key']); 
  82.     return $arr; 
  83.   } 
  84.  
  85.  
  86.   public function notify() 
  87.   { 
  88.     $config = array( 
  89.       'mch_id' => $this->mchid, 
  90.       'appid' => $this->appid, 
  91.       'key' => $this->apiKey, 
  92.     ); 
  93.     $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; 
  94.  
  95.     $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); 
  96.     if ($postObj === false) { 
  97.       die('parse xml error'); 
  98.     } 
  99.     if ($postObj->return_code != 'SUCCESS') { 
  100.       die($postObj->return_msg); 
  101.     } 
  102.     if ($postObj->result_code != 'SUCCESS') { 
  103.       die($postObj->err_code); 
  104.     } 
  105.     $arr = (array)$postObj; 
  106.     unset($arr['sign']); 
  107.     if (self::getSign($arr, $config['key']) == $postObj->sign) { 
  108.       echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; 
  109.       return $postObj; 
  110.     } 
  111.   } 
  112.  
  113.   /** 
  114.    * curl get 
  115.    * 
  116.    * @param string $url 
  117.    * @param array $options 
  118.    * @return mixed 
  119.    */ 
  120.   public static function curlGet($url = '', $options = array()) 
  121.   { 
  122.     $ch = curl_init($url); 
  123.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  124.     curl_setopt($ch, CURLOPT_TIMEOUT, 30); 
  125.     if (!emptyempty($options)) { 
  126.       curl_setopt_array($ch, $options); 
  127.     } 
  128.     //https请求 不验证证书和host 
  129.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  130.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  131.     $data = curl_exec($ch); 
  132.     curl_close($ch); 
  133.     return $data; 
  134.   } 
  135.  
  136.   public static function curlPost($url = '', $postData = '', $options = array()) 
  137.   { 
  138.     if (is_array($postData)) { 
  139.       $postData = http_build_query($postData); 
  140.     } 
  141.     $ch = curl_init(); 
  142.     curl_setopt($ch, CURLOPT_URL, $url); 
  143.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  144.     curl_setopt($ch, CURLOPT_POST, 1); 
  145.     curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 
  146.     curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 
  147.     if (!emptyempty($options)) { 
  148.       curl_setopt_array($ch, $options); 
  149.     } 
  150.     //https请求 不验证证书和host 
  151.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  152.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  153.     $data = curl_exec($ch); 
  154.     curl_close($ch); 
  155.     return $data; 
  156.   } 
  157.  
  158.   public static function createNonceStr($length = 16) 
  159.   { 
  160.     $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 
  161.     $str = ''; 
  162.     for ($i = 0; $i < $length; $i++) { 
  163.       $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 
  164.     } 
  165.     return $str; 
  166.   } 
  167.  
  168.   public static function arrayToXml($arr) 
  169.   { 
  170.     $xml = "<xml>"; 
  171.     foreach ($arr as $key => $val) { 
  172.       if (is_numeric($val)) { 
  173.         $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; 
  174.       } else 
  175.         $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; 
  176.     } 
  177.     $xml .= "</xml>"; 
  178.     return $xml; 
  179.   } 
  180.   /** 
  181.    * 获取签名 
  182.    */ 
  183.   public static function getSign($params, $key) 
  184.   { 
  185.     ksort($params, SORT_STRING); 
  186.     $unSignParaString = self::formatQueryParaMap($params, false); 
  187.     $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); 
  188.     return $signStr; 
  189.   } 
  190.  
  191.   protected static function formatQueryParaMap($paraMap, $urlEncode = false) 
  192.   { 
  193.     $buff = ""; 
  194.     ksort($paraMap); 
  195.     foreach ($paraMap as $k => $v) { 
  196.       if (null != $v && "null" != $v) { 
  197.         if ($urlEncode) { 
  198.           $v = urlencode($v); 
  199.         } 
  200.         $buff .= $k . "=" . $v . "&"; 
  201.       } 
  202.     } 
  203.     $reqPar = ''; 
  204.     if (strlen($buff) > 0) { 
  205.       $reqPar = substr($buff, 0, strlen($buff) - 1); 
  206.     } 
  207.     return $reqPar; 
  208.   } 
  209. }

Tags: php微信原生支付

分享到: