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.     protected $mchid; 
  70.     protected $appid; 
  71.     protected $appKey; 
  72.     protected $apiKey; 
  73.     public $data = null
  74.     public function __construct($mchid, $appid, $appKey,$key) 
  75.     { 
  76.         $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号 
  77.         $this->appid = $appid; //微信支付申请对应的公众号的APPID 
  78.         $this->appKey = $appKey; //微信支付申请对应的公众号的APP Key 
  79.         $this->apiKey = $key;   //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 
  80.     } 
  81.     /** 
  82.      * 通过跳转获取用户的openid,跳转流程如下: 
  83.      * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize 
  84.      * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code 
  85.      * @return 用户的openid 
  86.      */ 
  87.     public function GetOpenid() 
  88.     { 
  89.         //通过code获得openid 
  90.         if (!isset($_GET['code'])){ 
  91.             //触发微信返回code码 
  92.             $scheme = $_SERVER['HTTPS']=='on' ? 'https://' : 'http://'
  93.             $uri = $_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']; 
  94.             if($_SERVER['REQUEST_URI']) $uri = $_SERVER['REQUEST_URI']; 
  95.             $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$uri); 
  96.             $url = $this->__CreateOauthUrlForCode($baseUrl); 
  97.             Header("Location: $url"); 
  98.             exit(); 
  99.         } else { 
  100.             //获取code码,以获取openid 
  101.             $code = $_GET['code']; 
  102.             $openid = $this->getOpenidFromMp($code); 
  103.             return $openid; 
  104.         } 
  105.     } 
  106.     /** 
  107.      * 通过code从工作平台获取openid机器access_token 
  108.      * @param string $code 微信跳转回来带上的code 
  109.      * @return openid 
  110.      */ 
  111.     public function GetOpenidFromMp($code) 
  112.     { 
  113.         $url = $this->__CreateOauthUrlForOpenid($code); 
  114.         $res = self::curlGet($url); 
  115.         //取出openid 
  116.         $data = json_decode($res,true); 
  117.         $this->data = $data; 
  118.         $openid = $data['openid']; 
  119.         return $openid; 
  120.     } 
  121.     /** 
  122.      * 构造获取open和access_toke的url地址 
  123.      * @param string $code,微信跳转带回的code 
  124.      * @return 请求的url 
  125.      */ 
  126.     private function __CreateOauthUrlForOpenid($code) 
  127.     { 
  128.         $urlObj["appid"] = $this->appid; 
  129.         $urlObj["secret"] = $this->appKey; 
  130.         $urlObj["code"] = $code; 
  131.         $urlObj["grant_type"] = "authorization_code"
  132.         $bizString = $this->ToUrlParams($urlObj); 
  133.         return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; 
  134.     } 
  135.     /** 
  136.      * 构造获取code的url连接 
  137.      * @param string $redirectUrl 微信服务器回跳的url,需要url编码 
  138.      * @return 返回构造好的url 
  139.      */ 
  140.     private function __CreateOauthUrlForCode($redirectUrl) 
  141.     { 
  142.         $urlObj["appid"] = $this->appid; 
  143.         $urlObj["redirect_uri"] = "$redirectUrl"
  144.         $urlObj["response_type"] = "code"
  145.         $urlObj["scope"] = "snsapi_base"
  146.         $urlObj["state"] = "STATE"."#wechat_redirect"
  147.         $bizString = $this->ToUrlParams($urlObj); 
  148.         return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; 
  149.     } 
  150.     /** 
  151.      * 拼接签名字符串 
  152.      * @param array $urlObj 
  153.      * @return 返回已经拼接好的字符串 
  154.      */ 
  155.     private function ToUrlParams($urlObj) 
  156.     { 
  157.         $buff = ""
  158.         foreach ($urlObj as $k => $v) 
  159.         { 
  160.             if($k != "sign") $buff .= $k . "=" . $v . "&"
  161.         } 
  162.         $buff = trim($buff, "&"); 
  163.         return $buff; 
  164.     } 
  165.     /** 
  166.      * 统一下单 
  167.      * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid 
  168.      * @param float $totalFee 收款总费用 单位元 
  169.      * @param string $outTradeNo 唯一的订单号 
  170.      * @param string $orderName 订单名称 
  171.      * @param string $notifyUrl 支付结果通知url 不要有问号 
  172.      * @param string $timestamp 支付时间 
  173.      * @return string 
  174.      */ 
  175.     public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp) 
  176.     { 
  177.         $config = array( 
  178.             'mch_id' => $this->mchid, 
  179.             'appid' => $this->appid, 
  180.             'key' => $this->apiKey, 
  181.         ); 
  182.         //$orderName = iconv('GBK','UTF-8',$orderName); 
  183.         $unified = array( 
  184.             'appid' => $config['appid'], 
  185.             'attach' => 'pay',             //商家数据包,原样返回,如果填写中文,请注意转换为utf-8 
  186.             'body' => $orderName, 
  187.             'mch_id' => $config['mch_id'], 
  188.             'nonce_str' => self::createNonceStr(), 
  189.             'notify_url' => $notifyUrl, 
  190.             'openid' => $openid,            //rade_type=JSAPI,此参数必传 
  191.             'out_trade_no' => $outTradeNo, 
  192.             'spbill_create_ip' => '127.0.0.1'
  193.             'total_fee' => intval($totalFee * 100),       //单位 转为分 
  194.             'trade_type' => 'JSAPI'
  195.         ); 
  196.         $unified['sign'] = self::getSign($unified, $config['key']); 
  197.         $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified)); 
  198.         //禁止引用外部xml实体 
  199.         libxml_disable_entity_loader(true);      
  200.         $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA); 
  201.         if ($unifiedOrder === false) { 
  202.             die('parse xml error'); 
  203.         } 
  204.         if ($unifiedOrder->return_code != 'SUCCESS') { 
  205.             die($unifiedOrder->return_msg); 
  206.         } 
  207.         if ($unifiedOrder->result_code != 'SUCCESS') { 
  208.             die($unifiedOrder->err_code); 
  209.         } 
  210.         $arr = array( 
  211.             "appId" => $config['appid'], 
  212.             "timeStamp" => "$timestamp",        //这里是字符串的时间戳,不是int,所以需加引号 
  213.             "nonceStr" => self::createNonceStr(), 
  214.             "package" => "prepay_id=" . $unifiedOrder->prepay_id, 
  215.             "signType" => 'MD5'
  216.         ); 
  217.         $arr['paySign'] = self::getSign($arr, $config['key']); 
  218.         return $arr; 
  219.     } 
  220.     public static function curlGet($url = '', $options = array()) 
  221.     { 
  222.         $ch = curl_init($url); 
  223.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  224.         curl_setopt($ch, CURLOPT_TIMEOUT, 30); 
  225.         if (!empty($options)) { 
  226.             curl_setopt_array($ch, $options); 
  227.         } 
  228.         //https请求 不验证证书和host 
  229.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  230.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  231.         $data = curl_exec($ch); 
  232.         curl_close($ch); 
  233.         return $data; 
  234.     } 
  235.     public static function curlPost($url = '', $postData = '', $options = array()) 
  236.     { 
  237.         if (is_array($postData)) { 
  238.             $postData = http_build_query($postData); 
  239.         } 
  240.         $ch = curl_init(); 
  241.         curl_setopt($ch, CURLOPT_URL, $url); 
  242.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
  243.         curl_setopt($ch, CURLOPT_POST, 1); 
  244.         curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 
  245.         curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 
  246.         if (!empty($options)) { 
  247.             curl_setopt_array($ch, $options); 
  248.         } 
  249.         //https请求 不验证证书和host 
  250.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
  251.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 
  252.         $data = curl_exec($ch); 
  253.         curl_close($ch); 
  254.         return $data; 
  255.     } 
  256.     public static function createNonceStr($length = 16) 
  257.     { 
  258.         $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
  259.         $str = ''
  260.         for ($i = 0; $i < $length; $i++) { 
  261.             $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 
  262.         } 
  263.         return $str; 
  264.     } 
  265.     public static function arrayToXml($arr) 
  266.     { 
  267.         $xml = "<xml>"
  268.         foreach ($arr as $key => $val) { 
  269.             if (is_numeric($val)) { 
  270.                 $xml .= "<" . $key . ">" . $val . "</" . $key . ">"
  271.             } else 
  272.                 $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"
  273.         } 
  274.         $xml .= "</xml>"
  275.         return $xml; 
  276.     } 
  277.     public static function getSign($params, $key) 
  278.     { 
  279.         ksort($params, SORT_STRING); 
  280.         $unSignParaString = self::formatQueryParaMap($params, false); 
  281.         $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); 
  282.         return $signStr; 
  283.     } 
  284.     protected static function formatQueryParaMap($paraMap, $urlEncode = false
  285.     { 
  286.         $buff = ""
  287.         ksort($paraMap); 
  288.         foreach ($paraMap as $k => $v) { 
  289.             if (null != $v && "null" != $v) { 
  290.                 if ($urlEncode) { 
  291.                     $v = urlencode($v); 
  292.                 } 
  293.                 $buff .= $k . "=" . $v . "&"
  294.             } 
  295.         } 
  296.         $reqPar = ''
  297.         if (strlen($buff) > 0) { 
  298.             $reqPar = substr($buff, 0, strlen($buff) - 1); 
  299.         } 
  300.         return $reqPar; 
  301.     } 

 

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

支付宝扫一扫打赏

微信扫一扫打赏

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

文章点评

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

添加微信好友

添加微信好友

微信小程序

百度小程序