QQ咨询 官方微信

添加微信好友

官方小程序

百度小程序

微信小程序

头条小程序

关于我们

PHP基础

微信之微信支付(封装)--jsapi

 admin  2020-12-06 21:26:43
  1. <?php 
  2. header('Content-type:text/html; Charset=utf-8'); 
  3. $mchid = '';          //微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送 
  4. $appid = '';  //微信支付申请对应的公众号的APPID 
  5. $appKey = '';   //微信支付申请对应的公众号的APP Key 
  6. $apiKey = '';   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 
  7. //①、获取用户openid 
  8. $wxPay = new WxpayService($mchid,$appid,$appKey,$apiKey); 
  9. $openId = $wxPay->GetOpenid();      //获取openid 
  10. if(!$openId) exit('获取openid失败'); 
  11. //②、统一下单 
  12. $outTradeNo = uniqid();     //你自己的商品订单号 
  13. $payAmount = 0.01;          //付款金额,单位:元 
  14. $orderName = '支付测试';    //订单标题 
  15. $notifyUrl = 'https://www.xxx.com/wx/notify.php';     //付款成功后的回调地址(不要有问号) 
  16. $payTime = time();      //付款时间 
  17. $jsApiParameters = $wxPay->createJsBizPackage($openId,$payAmount,$outTradeNo,$orderName,$notifyUrl,$payTime); 
  18. $jsApiParameters = json_encode($jsApiParameters); 
  19. ?> 
  20.     <html> 
  21.     <head> 
  22.         <meta charset="utf-8" /> 
  23.         <meta name="viewport" content="width=device-width, initial-scale=1"/> 
  24.         <title>微信支付样例-支付</title> 
  25.         <script type="text/javascript"> 
  26.             //调用微信JS api 支付 
  27.             function jsApiCall() 
  28.             { 
  29.                 WeixinJSBridge.invoke( 
  30.                     'getBrandWCPayRequest', 
  31.                     <?php echo $jsApiParameters; ?>, 
  32.                     function(res){ 
  33.                         WeixinJSBridge.log(res.err_msg); 
  34.                         if(res.err_msg=='get_brand_wcpay_request:ok'){ 
  35.                             alert('支付成功!'); 
  36.                         }else{ 
  37.                             alert('支付失败:'+res.err_code+res.err_desc+res.err_msg); 
  38.                         } 
  39.                     } 
  40.                 ); 
  41.             } 
  42.             function callpay() 
  43.             { 
  44.                 if (typeof WeixinJSBridge == "undefined"){ 
  45.                     if( document.addEventListener ){ 
  46.                         document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); 
  47.                     }else if (document.attachEvent){ 
  48.                         document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
  49.                         document.attachEvent('onWeixinJSBridgeReady', jsApiCall); 
  50.                     } 
  51.                 }else{ 
  52.                     jsApiCall(); 
  53.                 } 
  54.             } 
  55.         </script> 
  56.     </head> 
  57.     <body> 
  58.  
  59.     <h1>微信支付</h1> 
  60.     <br/> 
  61.     <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px"><?php echo $payAmount?>元</span>钱</b></font><br/><br/> 
  62.     <div align="center"> 
  63.         <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >立即支付</button> 
  64.     </div> 
  65.     </body> 
  66.     </html> 
  67. <?php 
  68. class WxpayService 
  69. { 
  70.     protected $mchid; 
  71.     protected $appid; 
  72.     protected $appKey; 
  73.     protected $apiKey; 
  74.     public $data = null; 
  75.     public function __construct($mchid, $appid, $appKey,$key) 
  76.     { 
  77.         $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号 
  78.         $this->appid = $appid; //微信支付申请对应的公众号的APPID 
  79.         $this->appKey = $appKey; //微信支付申请对应的公众号的APP Key 
  80.         $this->apiKey = $key;   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 
  81.     } 
  82.     /** 
  83.      * 通过跳转获取用户的openid,跳转流程如下: 
  84.      * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize 
  85.      * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code 
  86.      * @return 用户的openid 
  87.      */ 
  88.     public function GetOpenid() 
  89.     { 
  90.         //通过code获得openid 
  91.         if (!isset($_GET['code'])){ 
  92.             //触发微信返回code码 
  93.             $scheme = $_SERVER['HTTPS']=='on' ? 'https://' : 'http://'; 
  94.             $uri = $_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']; 
  95.             if($_SERVER['REQUEST_URI']) $uri = $_SERVER['REQUEST_URI']; 
  96.             $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$uri); 
  97.             $url = $this->__CreateOauthUrlForCode($baseUrl); 
  98.             Header("Location: $url"); 
  99.             exit(); 
  100.         } else { 
  101.             //获取code码,以获取openid 
  102.             $code = $_GET['code']; 
  103.             $openid = $this->getOpenidFromMp($code); 
  104.             return $openid; 
  105.         } 
  106.     } 
  107.     /** 
  108.      * 通过code从工作平台获取openid机器access_token 
  109.      * @param string $code 微信跳转回来带上的code 
  110.      * @return openid 
  111.      */ 
  112.     public function GetOpenidFromMp($code) 
  113.     { 
  114.         $url = $this->__CreateOauthUrlForOpenid($code); 
  115.         $res = self::curlGet($url); 
  116.         //取出openid 
  117.         $data = json_decode($res,true); 
  118.         $this->data = $data; 
  119.         $openid = $data['openid']; 
  120.         return $openid; 
  121.     } 
  122.     /** 
  123.      * 构造获取open和access_toke的url地址 
  124.      * @param string $code,微信跳转带回的code 
  125.      * @return 请求的url 
  126.      */ 
  127.     private function __CreateOauthUrlForOpenid($code) 
  128.     { 
  129.         $urlObj["appid"] = $this->appid; 
  130.         $urlObj["secret"] = $this->appKey; 
  131.         $urlObj["code"] = $code; 
  132.         $urlObj["grant_type"] = "authorization_code"; 
  133.         $bizString = $this->ToUrlParams($urlObj); 
  134.         return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; 
  135.     } 
  136.     /** 
  137.      * 构造获取code的url连接 
  138.      * @param string $redirectUrl 微信服务器回跳的url,需要url编码 
  139.      * @return 返回构造好的url 
  140.      */ 
  141.     private function __CreateOauthUrlForCode($redirectUrl) 
  142.     { 
  143.         $urlObj["appid"] = $this->appid; 
  144.         $urlObj["redirect_uri"] = "$redirectUrl"; 
  145.         $urlObj["response_type"] = "code"; 
  146.         $urlObj["scope"] = "snsapi_base"; 
  147.         $urlObj["state"] = "STATE"."#wechat_redirect"; 
  148.         $bizString = $this->ToUrlParams($urlObj); 
  149.         return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; 
  150.     } 
  151.     /** 
  152.      * 拼接签名字符串 
  153.      * @param array $urlObj 
  154.      * @return 返回已经拼接好的字符串 
  155.      */ 
  156.     private function ToUrlParams($urlObj) 
  157.     { 
  158.         $buff = ""; 
  159.         foreach ($urlObj as $k => $v) 
  160.         { 
  161.             if($k != "sign") $buff .= $k . "=" . $v . "&"; 
  162.         } 
  163.         $buff = trim($buff, "&"); 
  164.         return $buff; 
  165.     } 
  166.     /** 
  167.      * 统一下单 
  168.      * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid 
  169.      * @param float $totalFee 收款总费用 单位元 
  170.      * @param string $outTradeNo 唯一的订单号 
  171.      * @param string $orderName 订单名称 
  172.      * @param string $notifyUrl 支付结果通知url 不要有问号 
  173.      * @param string $timestamp 支付时间 
  174.      * @return string 
  175.      */ 
  176.     public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp) 
  177.     { 
  178.         $config = array( 
  179.             'mch_id' => $this->mchid, 
  180.             'appid' => $this->appid, 
  181.             'key' => $this->apiKey, 
  182.         ); 
  183.         //$orderName = iconv('GBK','UTF-8',$orderName); 
  184.         $unified = array( 
  185.             'appid' => $config['appid'], 
  186.             'attach' => 'pay',             //商家数据包,原样返回,如果填写中文,请注意转换为utf-8 
  187.             'body' => $orderName, 
  188.             'mch_id' => $config['mch_id'], 
  189.             'nonce_str' => self::createNonceStr(), 
  190.             'notify_url' => $notifyUrl, 
  191.             'openid' => $openid,            //rade_type=JSAPI,此参数必传 
  192.             'out_trade_no' => $outTradeNo, 
  193.             'spbill_create_ip' => '127.0.0.1', 
  194.             'total_fee' => intval($totalFee * 100),       //单位 转为分 
  195.             'trade_type' => 'JSAPI', 
  196.         ); 
  197.         $unified['sign'] = self::getSign($unified, $config['key']); 
  198.         $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified)); 
  199.         //禁止引用外部xml实体 
  200.         libxml_disable_entity_loader(true);      
  201.         $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA); 
  202.         if ($unifiedOrder === false) { 
  203.             die('parse xml error'); 
  204.         } 
  205.         if ($unifiedOrder->return_code != 'SUCCESS') { 
  206.             die($unifiedOrder->return_msg); 
  207.         } 
  208.         if ($unifiedOrder->result_code != 'SUCCESS') { 
  209.             die($unifiedOrder->err_code); 
  210.         } 
  211.         $arr = array( 
  212.             "appId" => $config['appid'], 
  213.             "timeStamp" => "$timestamp",        //这里是字符串的时间戳,不是int,所以需加引号 
  214.             "nonceStr" => self::createNonceStr(), 
  215.             "package" => "prepay_id=" . $unifiedOrder->prepay_id, 
  216.             "signType" => 'MD5', 
  217.         ); 
  218.         $arr['paySign'] = self::getSign($arr, $config['key']); 
  219.         return $arr; 
  220.     } 
  221.     public static function curlGet($url = '', $options = array()) 
  222.     { 
  223.         $ch = curl_init($url); 
  224.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  225.         curl_setopt($ch, CURLOPT_TIMEOUT, 30); 
  226.         if (!empty($options)) { 
  227.             curl_setopt_array($ch, $options); 
  228.         } 
  229.         //https请求 不验证证书和host 
  230.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  231.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  232.         $data = curl_exec($ch); 
  233.         curl_close($ch); 
  234.         return $data; 
  235.     } 
  236.     public static function curlPost($url = '', $postData = '', $options = array()) 
  237.     { 
  238.         if (is_array($postData)) { 
  239.             $postData = http_build_query($postData); 
  240.         } 
  241.         $ch = curl_init(); 
  242.         curl_setopt($ch, CURLOPT_URL, $url); 
  243.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  244.         curl_setopt($ch, CURLOPT_POST, 1); 
  245.         curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 
  246.         curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 
  247.         if (!empty($options)) { 
  248.             curl_setopt_array($ch, $options); 
  249.         } 
  250.         //https请求 不验证证书和host 
  251.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  252.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  253.         $data = curl_exec($ch); 
  254.         curl_close($ch); 
  255.         return $data; 
  256.     } 
  257.     public static function createNonceStr($length = 16) 
  258.     { 
  259.         $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; 
  260.         $str = ''; 
  261.         for ($i = 0; $i < $length; $i++) { 
  262.             $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 
  263.         } 
  264.         return $str; 
  265.     } 
  266.     public static function arrayToXml($arr) 
  267.     { 
  268.         $xml = "<xml>"; 
  269.         foreach ($arr as $key => $val) { 
  270.             if (is_numeric($val)) { 
  271.                 $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; 
  272.             } else 
  273.                 $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; 
  274.         } 
  275.         $xml .= "</xml>"; 
  276.         return $xml; 
  277.     } 
  278.     public static function getSign($params, $key) 
  279.     { 
  280.         ksort($params, SORT_STRING); 
  281.         $unSignParaString = self::formatQueryParaMap($params, false); 
  282.         $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); 
  283.         return $signStr; 
  284.     } 
  285.     protected static function formatQueryParaMap($paraMap, $urlEncode = false) 
  286.     { 
  287.         $buff = ""; 
  288.         ksort($paraMap); 
  289.         foreach ($paraMap as $k => $v) { 
  290.             if (null != $v && "null" != $v) { 
  291.                 if ($urlEncode) { 
  292.                     $v = urlencode($v); 
  293.                 } 
  294.                 $buff .= $k . "=" . $v . "&"; 
  295.             } 
  296.         } 
  297.         $reqPar = ''; 
  298.         if (strlen($buff) > 0) { 
  299.             $reqPar = substr($buff, 0, strlen($buff) - 1); 
  300.         } 
  301.         return $reqPar; 
  302.     } 
  303. } 

 

¥ 打赏
×
如果您觉得文章帮助了您就打赏一下吧
非常感谢你的打赏,我们将继续分享更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

本文《微信之微信支付(封装)--jsapi》发布于石头博客文章,作者:admin,如若转载,请注明出处:https://www.pweb123.com/html/php/820.html,否则禁止转载,谢谢配合!

文章点评

我来说两句 已有0条评论
点击图片更换

添加微信好友

添加微信好友

微信小程序

百度小程序