侧边栏壁纸
博主头像
祥拓软件

欢迎访问,如有问题请发送邮件至:work@work100.com.cn

  • 累计撰写 36 篇文章
  • 累计创建 9 个标签
  • 累计收到 1 条评论

异次元发卡官方微信支付功能增强

祥拓软件
2022-01-10 / 0 评论 / 1 点赞 / 311 阅读 / 10,791 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-01-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
  1. 安装本站的 微信登录插件
    蓝奏云下载地址:https://wwi.lanzouj.com/i52H3yl1rle
  2. 在后台插件里配置微信公众号参数
  3. 修改代码:
    App/Pay/WeChat/Impl/Pay.php 为下面代码
<?php
declare(strict_types=1);

namespace App\Pay\WeChat\Impl;


use App\Util\Client;
use App\Entity\PayEntity;
use App\Pay\Base;
use Kernel\Exception\JSONException;

class Pay extends Base implements \App\Pay\Pay
{

    /**
     * @throws \Kernel\Exception\JSONException
     */
    public function trade(): PayEntity
    {
        $params = new \Yurun\PaySDK\Weixin\Params\PublicParams();
        $params->appID = $this->config['app_id'];
        $params->mch_id = $this->config['mch_id'];
        $params->key = $this->config['key'];
        $pay = new \Yurun\PaySDK\Weixin\SDK($params);
        if (Client::isMobile()) {
            if (Client::isWxMobile()) {
                return $this->jsApi($pay);
            } else {
                return $this->h5($pay);
            }
        } else {
            return $this->scanCode($pay);
        }
        // return match ((int)$this->code) {
        //     1 => $this->scanCode($pay),
        //     2 => $this->h5($pay)
        // };
    }

 /**
  *     jsApi
     * @throws \Kernel\Exception\JSONException
     */
    private function jsApi(\Yurun\PaySDK\Weixin\SDK $pay): PayEntity
    {
        
        try {
            // 支付接口
            $request = new \Yurun\PaySDK\Weixin\JSAPI\Params\Pay\Request;
            $request->appid = $this->appID;
            $request->body = $this->tradeNo; // 商品描述
            $request->out_trade_no = $this->tradeNo; // 订单号
            $request->total_fee = $this->amount * 100; // 订单总金额,单位为:分
            $request->spbill_create_ip = $this->clientIp; // 客户端ip
            $request->notify_url = $this->callbackUrl; // 异步通知地址
            $request->openid = $_SESSION[\App\Consts\User::WECHAT_SESSION];
            $result = $pay->execute($request);
            if ($pay->checkResult()) {
                $request = new \Yurun\PaySDK\Weixin\JSAPI\Params\JSParams\Request();
                $request->prepay_id = $result['prepay_id'];
                $jsapiParams = $pay->execute($request);
                $payEntity = new PayEntity();
                $payEntity->setType(self::TYPE_REDIRECT);
                $payEntity->setUrl('/jsWxPay.php?data=' . json_encode($jsapiParams));
                return $payEntity;
            } else {
                $this->log($pay->getError());
                throw new JSONException($pay->getError());
            }
        } catch (\Error | \Exception $e) {
            $this->log($e->getMessage());
            throw new JSONException($e->getMessage());
        }

    }
    
    /**
     * 扫码支付
     * @throws \Kernel\Exception\JSONException
     */
    private function scanCode(\Yurun\PaySDK\Weixin\SDK $pay): PayEntity
    {
        try {
            $request = new \Yurun\PaySDK\Weixin\Native\Params\Pay\Request;
            $request->body = $this->tradeNo; // 商品描述
            $request->out_trade_no = $this->tradeNo; // 订单号
            $request->total_fee = $this->amount * 100; // 订单总金额,单位为:分
            $request->spbill_create_ip = $this->clientIp; // 客户端ip
            $request->notify_url = $this->callbackUrl; // 异步通知地址
            $result = $pay->execute($request);
            $shortUrl = $result['code_url'];
            if (!$shortUrl) {
                $this->log("没有获取到二维码");
                throw new JSONException("下单失败,请联系客服");
            }
            $payEntity = new PayEntity();
            $payEntity->setType(self::TYPE_LOCAL_RENDER);
            $payEntity->setUrl($shortUrl);
            $payEntity->setOption(['returnUrl' => $this->returnUrl]);
            return $payEntity;
        } catch (\Error | \Exception $e) {
            $this->log($e->getMessage());
            throw new JSONException($e->getMessage());
        }
    }

    /**
     * @throws \Kernel\Exception\JSONException
     */
    private function h5(\Yurun\PaySDK\Weixin\SDK $pay): PayEntity
    {
        // 支付接口
        $request = new \Yurun\PaySDK\Weixin\H5\Params\Pay\Request;
        $request->body = $this->tradeNo; // 商品描述
        $request->out_trade_no = $this->tradeNo; // 订单号
        $request->total_fee = $this->amount * 100; // 订单总金额,单位为:分
        $request->spbill_create_ip = $this->clientIp; // 客户端ip
        $request->notify_url = $this->callbackUrl; // 异步通知地址
        // 调用接口
        $result = $pay->execute($request);
        if ($pay->checkResult()) {
            // 跳转支付界面
            $url = $result['mweb_url'];
            if (!$url) {
                $this->log("没有捕获到支付地址");
                throw new JSONException("下单失败,请联系客服");
            }
            $payEntity = new PayEntity();
            $payEntity->setType(self::TYPE_REDIRECT);
            $payEntity->setUrl($url);
            return $payEntity;
        } else {
            $this->log($pay->getError());
            throw new JSONException($pay->getError());
        }
    }
}

修改App\Controller\User\Index.php

<?php
declare(strict_types=1);

namespace App\Controller\User;


use App\Controller\Base\View\User;
use App\Interceptor\UserVisitor;
use App\Interceptor\Waf;
use App\Model\Config;
use App\Util\Plugin;
use App\Util\Client;
use Kernel\Annotation\Interceptor;

#[Interceptor([Waf::class, UserVisitor::class])]
class Index extends User
{
    /**
     * @return string
     * @throws \Kernel\Exception\ViewException|\Kernel\Exception\JSONException|\ReflectionException
     */
      public function index(): string
    {
        if ((int)Config::get("closed") == 1) {
            return $this->theme("店铺正在维护", "CLOSED", "Index/Closed.html");
        }
        $session = $_SESSION[\App\Consts\User::WECHAT_SESSION];
        if (empty($session) && Client::isMobile() && Client::isWxMobile()) {
            $config = Plugin::getConfig("WechatLogin");
            $url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$config['appid'].'&redirect_uri='. $config['redirect_uri'] .'&response_type=code&scope=snsapi_base&state='.time().'#wechat_redirect';
            
            return $this->theme("首页", "WechatLogin", "Index/WechatLogin.html", ['url' => $url]);
        } else {
            $from = (int)$_GET['from'];
    
            $map = [];
            parse_str(base64_decode(urldecode((string)$_GET['code'])), $map);
    
            if ($map['from']) {
                $from = $map['from'];
            }
    
            $map['a'] = $map['a'] ? $map['a'] : Config::get("default_category");
    
    
            return $this->theme("首页", "INDEX", "Index/Index.html", ['user' => $this->getUser(), 'from' => $from, "categoryId" => $map['a'], "commodityId" => $map['b']]);
        }
    }

    /**
     * @return string
     * @throws \Kernel\Exception\ViewException|\ReflectionException
     */
    public function query(): string
    {
        $tradeNo = (string)$_GET['tradeNo'];
        $user = $this->getUser();

        if ($user) {
            Client::redirect("/user/personal/purchaseRecord" . ($tradeNo != "" ? "?tradeNo=" . $tradeNo : ""), "正在跳转..", 0);
        }

        return $this->theme("订单查询", "QUERY", "Index/Query.html", ['user' => $user, 'tradeNo' => $tradeNo]);
    }
}

修改代码 App\Consts\User.php

<?php
declare(strict_types=1);

namespace App\Consts;


interface User
{
    const SESSION = "USER_SESSION";
    
    const WECHAT_SESSION = "WECHAT_USER_SESSION";
}

在站点跟目录增加 jsWxPay.php 代码为:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>欢迎使用微信付款!</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script src="https://cdn.bootcss.com/layer/2.3/layer.js"></script>
    <style type="text/css">
        .hr-top {
            margin-top: 20px;
            border-top: 1px dashed #e5e5e5;
            padding: 10px 0;
            position: relative;
        }
    </style>
    <link href="/app/Pay/WeChat/Assets/css/pay.css" rel="stylesheet" type="text/css">
</head>

<body>
<div class="body">
    <h1 class="mod-title">
        <span class="ico_log ico-wxsm" style="margin-left: 50px;"></span>
    </h1>

    <div class="mod-ct" style="margin-top: 2px;">

        <div class="pc">
            <div style="font-size: 32px;padding-top: 20px;">
                请在微信弹窗中支付!
            </div>
        </div>
    </div>
    <script type="text/javascript">
       function getParam(name) {
            var str = decodeURI(window.location.href)
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
            var r = str.split("?")[1].match(reg); //匹配目标参数
            if (r != null) {
                return decodeURIComponent(r[2]);
     
            }
            return null; //返回参数值
        }
        const data = getParam('data')
        function onBridgeReady(){
           WeixinJSBridge.invoke(
                'getBrandWCPayRequest', {
                    ...JSON.parse(decodeURI(data))
                },
                function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ){
                    layer.confirm('支付成功,请在订单查询中查询详细信息', {icon: 1, title:'支付提示'}, function(index){
                        window.location.href = "/";
                    });
                } else {
                    alert('支付失败')
                    window.location.href = '/'
                }
           }); 
        }
        if (typeof WeixinJSBridge == "undefined"){
           if( document.addEventListener ){
               document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
           }else if (document.attachEvent){
               document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
               document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
           }
        }else{
           onBridgeReady();
        }
    </script>
</div>
</body>
</html>

修改代码:/app/Util/Client

<?php
declare(strict_types=1);

namespace App\Util;

use JetBrains\PhpStorm\NoReturn;
use Kernel\Util\View;

/**
 * Class Client
 * @package App\Util
 */
class Client
{
    /*
     * 获取客户端IP地址
     * @return string
     */
    public static function getAddress(): string
    {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            return (string)$arr[0];
        }

        return (string)$_SERVER['REMOTE_ADDR'];
    }

    /**
     * 获取URL地址
     * @return string
     */
    public static function getUrl(): string
    {
        if (strtolower((string)$_SERVER["HTTPS"]) == "on") {
            $_SERVER['REQUEST_SCHEME'] = "https";
        } elseif (!isset($_SERVER['REQUEST_SCHEME'])) {
            $_SERVER['REQUEST_SCHEME'] = "http";
        }
        return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'];
    }

    /**
     * @return string
     */
    public static function getDomain(): string
    {
        $host = explode(":", (string)$_SERVER['HTTP_HOST']);
        return (string)$host[0];
    }

    /**
     * 重定向浏览器地址
     * @param string $url
     * @param string $message
     * @param int $time
     */
    #[NoReturn] public static function redirect(string $url, string $message, int $time = 2): void
    {
        if ($time == 0) {
            header('location:' . $url);
        } else {
            header("refresh:{$time},url={$url}");
            echo View::render("404.html", ["msg" => $message]);
        }
        exit;
    }

  /**
    * 判断是否为微信浏览器
    */
    public static function isWxMobile(): bool {
        return (bool)stristr($_SERVER['HTTP_USER_AGENT'],'MicroMessenger');
    }

    /**
     * 判断是否手机访问
     * @return bool
     */
    public static function isMobile(): bool
    {
        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
            return true;
        }
        if (isset($_SERVER['HTTP_VIA'])) {
            return (bool)stristr($_SERVER['HTTP_VIA'], "wap");
        }
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $clientkeywords = array('nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu', 'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi', 'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile', 'MicroMessenger');
            if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
                return true;
            }
        }
        if (isset ($_SERVER['HTTP_ACCEPT'])) {
            if ((str_contains($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml')) && (!str_contains($_SERVER['HTTP_ACCEPT'], 'text/html') || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
                return true;
            }
        }
        return false;
    }
}

增加HTML文件:
在 /app/View/User/Theme/Cartoon/Index/ 下创建 WechatLogin.html

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>跳转中</title>
</head>

<body>
<div class="body">
    <script type="text/javascript">
        window.location.href = '#{$url}'
    </script>
</div>
</body>
</html>

修改插件里的回调地址:
/app/Plugin/WorkWechatLogin/Config 中的redirect_uri 为
https://xxxxx/plugin/WorkWechatLogin/api/getOpenId
没有就按照格式手动加一个

1
博主关闭了当前页面的评论