够意思博客够意思博客够意思博客

EasySwoole 实现微信JSAPI支付

安装EasySwoole支付SDK

composer require easyswoole/pay

配置信息

需要在公众号和商户号授权当前项目域名

添加微信支付配置信息,并将证书上传至根目录

/**################ 微信支付配置 CONFIG ##################*/
'WX'         => [
   'AppId'          => '微信公众号APPID',
   'Secret'          => '微信公众号Secret',
   'MchId'          => '商户号ID',
   'Key'          => '商户支付秘钥',
   'ApiClientCert'          => EASYSWOOLE_ROOT.'/apiclient_cert.pem',
   'ApiClientKey'          => EASYSWOOLE_ROOT.'/apiclient_key.pem',
],

代码实现

支付流程:通过网页授权获取用户OPENID->请求微信统一下单接口->微信内H5网页发起支付请求

创建http控制器\App\HttpController\Pay.php

<?php
namespace App\HttpController;

use EasySwoole\EasySwoole\Config;
use EasySwoole\Http\AbstractInterface\Controller;

class Pay extends Controller
{
   protected $param;  //请求参数
   protected $wechatConfig ; //微信配置信息
   protected function onRequest(?string $action): ?bool
   {
       $this->param = $this->request()->getRequestParam(); //接收请求参数
       $this->wechatConfig = Config::getInstance()->getConf('WX');
       return true;
   }
   /**
    * JSAPI支付
    */
   public function index()
   {
       $params = $this->request()->getRequestParam();
       if(!isset($params['code'])){
           $this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
           $scope = "snsapi_base";
           $state = md5(time());
           $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->wechatConfig['AppId']."&redirect_uri=http://www.go1s.cn/pay/index?response_type=code&scope=".$scope."&state=".$state."#wechat_redirect";
           $this->response()->redirect($url);
           return false;
       }else {
           //code获取access_token
           $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->wechatConfig['AppId']."&secret=".$this->wechatConfig['Secret']."&code=".$this->param["code"]."&grant_type=authorization_code";
           //获取  access_token openid scope
           $res = \EasySwoole\Pay\Utility\NewWork::get($url,[])->getBody();  //$this->https_request($url);
           $res  = json_decode($res,true);
           $openid = $res["openid"];    //当前用户的openid
           $access_token = $res["access_token"];  //access_token 获取共享收货地址参数需要次参数
                       $wechatConfig = new \EasySwoole\Pay\WeChat\Config();
           $wechatConfig->setAppId($this->wechatConfig['AppId']);      // 公众号APPID
           $wechatConfig->setMchId($this->wechatConfig['MchId']);          //商户号
                       $wechatConfig->setKey($this->wechatConfig['Key']);//支付key
           $wechatConfig->setNotifyUrl('http://www.go1s.cn/pay/notify'); //支付回调地址
                       $wechatConfig->setApiClientCert($this->wechatConfig['ApiClientCert']);//客户端证书
                       $wechatConfig->setApiClientKey($this->wechatConfig['ApiClientKey']); //客户端证书秘钥

                       $officialAccount = new \EasySwoole\Pay\WeChat\RequestBean\OfficialAccount();
           $officialAccount->setOpenid($openid);
           $outTradeNo = 'CN' . date('YmdHis') . rand(1000, 9999);
           echo "MP--- " . $outTradeNo . "\r\n";
           $officialAccount->setOutTradeNo($outTradeNo);
           $officialAccount->setBody('xxxxx-测试' . $outTradeNo);
           $officialAccount->setTotalFee(1);
           $officialAccount->setSpbillCreateIp($this->getClientIp());
           $pay = new \EasySwoole\Pay\Pay();

           $params = $pay->weChat($wechatConfig)->officialAccount($officialAccount);
           $jsApiParameters = $params->toArray();
           $str = <<<EOF
   <html>
   <head>
       <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
       <meta name="viewport" content="width=device-width, initial-scale=1"/>
       <title>微信JSAPI支付-订单支付</title>
       <script type="text/javascript" charset="UTF-8" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
       <script type="text/javascript">
           //调用微信JS api 支付
           function jsApiCall() {
               WeixinJSBridge.invoke(
                   'getBrandWCPayRequest',
                   {'appId':'{$jsApiParameters['appId']}',
                   'nonceStr':'{$jsApiParameters['nonceStr']}',
                   'package':'{$jsApiParameters['package']}',
                   'signType':'{$jsApiParameters['signType']}',
                   'timeStamp':'{$jsApiParameters['timeStamp']}',
                   'paySign':'{$jsApiParameters['paySign']}'},
                   function (res) {
                        WeixinJSBridge.log(res.err_msg);
                       //alert(res.err_code+res.err_desc+res.err_msg);
                       if(res.err_msg=='get_brand_wcpay_request:cancel'){
                           alert("您已取消支付,即将跳转取消支付页面");
                           window.location.href="/Pay/payCancel";
                           return false;
                       }
                       if(res.err_msg=='get_brand_wcpay_request:fail'){
                           alert("支付失败,即将跳转错误页面");
                           window.location.href="/Pay/payError";
                           return false;
                       }
                       if(res.err_msg=='get_brand_wcpay_request:ok'){
                           alert("支付成功,即将跳转成功页面");
                           //完成之后的一些逻辑
                           window.location.href="/Pay/paySuccess";
                       }
                   }
               );
           }
   
           function callpay() {
               if (typeof WeixinJSBridge == "undefined") {
                   if (document.addEventListener) {
                       document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                   } else if (document.attachEvent) {
                       document.attachEvent('WeixinJSBridgeReady', jsApiCall);
                       document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                   }
               } else {
                   jsApiCall();
               }
           }
       </script>
   </head>
   <body>
   <br/>
   
   <div align="center">
   <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1</span></b></font><br/><br/>
       <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>
   </div>
   </body>
   </html>
EOF;
           $this->response()->write($str);
       }
   }
   
   /**
    * JSAPI支付异步回调
    */
   public function notify(){
       $content = $this->request()->getBody()->__toString();
       $pay = new \EasySwoole\Pay\Pay();
       $wechatConfig = new \EasySwoole\Pay\WeChat\Config();
       $wechatConfig->setAppId($this->wechatConfig['AppId']);      // 公众号APPID
       $wechatConfig->setMchId($this->wechatConfig['MchId']);          //商户号
               $wechatConfig->setKey($this->wechatConfig['Key']);//支付key
       $wechatConfig->setNotifyUrl('http://www.go1s.cn/pay/notify'); //支付回调地址
               $wechatConfig->setApiClientCert($this->wechatConfig['ApiClientCert']);//客户端证书
               $wechatConfig->setApiClientKey($this->wechatConfig['ApiClientKey']); //客户端证书秘钥
               $data = $pay->weChat($wechatConfig)->verify($content);
       $msg = "[" . date('Y-m-d H:i:s') . "]" . $data->__toString() . "\r\n";
       file_put_contents(EASYSWOOLE_ROOT. '/Temp/notify-' . date('Y-m-d') . '.log', $msg, FILE_APPEND);
       $this->response()->write(\EasySwoole\Pay\WeChat\WeChat::success());
   }

   /**
    * http携程客户端请求微信API
    */
   public function https_request($url, $data = [])
   {
       //实例化 http携程客户端
       $client = new \EasySwoole\HttpClient\HttpClient($url);
       $response = $client->get();
       return $response->getBody();
   }

   /**
    * 获取当前客户端IP
    */
   protected function getClientIp(){
       if (count($this->request()->getHeader('x-real-ip'))) {
           $ip = $this->request()->getHeader('x-real-ip')[0];
       } else {
           $params = $this->request()->getServerParams();
           foreach (['http_client_ip', 'http_x_forward_for', 'x_real_ip', 'remote_addr'] as $key) {
               if (isset($params[$key]) && !strcasecmp($params[$key], 'unknown')) {
                   $ip = $params[$key];
                   break;
               }
           }
       }
       return $ip;
   }

   /**
    * 支付成功
    */
   public function paySuccess(){
       $this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
       $this->response()->write('<h1>支付成功</h1>');
   }

   /**
    * 支付错误
    */
   public function payError(){
       $this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
       $this->response()->write('<h1>支付异常</h1>');
   }

   /**
    * 取消支付
    */
   public function payCancel(){
       $this->response()->withHeader('Content-type', 'text/html;charset=utf-8');
       $this->response()->write('<h1>取消支付</h1>');
   }

   /**
    * 异常抛出
    **/
   public function onException(\Throwable $throwable): void
   {
       $path = $this->request()->getUri()->getPath();
       $this->writeJson(\EasySwoole\Http\Message\Status::CODE_INTERNAL_SERVER_ERROR, $throwable->getMessage(), "服务器异常");

   }
}

查看结果

微信访问支付链接 http://域名:端口/pay/index  

EasySwoole 实现微信JSAPI支付(图1)

本文为够意思原创文章,转载无需和我联系,但请注明来自够意思博客blog.go1s.cn:够意思博客 » EasySwoole 实现微信JSAPI支付

加载中~