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

Tags: php微信原生支付

分享到: