账户中心 退出系统
开发文档 资讯·分享 技术交流 会员登录
phpGrace GSCMS 公众号系统
JSAPI 支付

JSAPI 支付介绍

JSAPI 支付是指商户通过调用微信支付提供的 JSAPI 接口,在支付场景中调起微信支付模块完成收款。
应用场景有:
1 线下场所:调用接口生成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付
2 公众号场景:用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
3 PC网站场景:在网站中展示二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付

JSAPI 必要条件

1 已认证的公众号 ( 服务号或者符合微信官方要求的订阅号 )
2 微信支付商户申请并开通 JSAPI 支付产品
3 公众号与微信支付关联 :
    3.1 微信支付 > 产品大全 > JSAPI 支付 > 产品配置 > AppID 管理 > 关联 AppID
    3.2 公众号账户中心 > 微信支付 > 商户号管理
4 微信支付授权目录 : 微信支付 > 产品大全 > JSAPI 支付 > 开发配置 > 添加 JSAPI 开发目录
5 公众号网页授权域名 : 公众号管理中心 > 设置与开发 > 接口权限 > 网页授权获取用户信息 > 修改

框架配置

打开 /phpGrace/configs/weChat.php,正确填写以下配置信息

<?php
// 微信开发配置
return array(
    /* -------- 微信公众号基础配置 -------- */
    'wechatBase'  => array(
        // 公众号 appId
        'appid'           => 'wx****',
        // 公众号 AppSecert
        'secert'          => '******',
        // Token 用于接口认证
        'token'           => '******',
        // accessTokenFile 数据文件路径
        'accessTokenFile' => './accessTokenFile.php'
    ),

    /* -------- 微信支付 [ JSAPI ] 需要的配置 -------- */
    'JSAPI'       => array(
        // 此处的 AppID 与上面的基础公众号 ID 一致
        'appid'   => 'wx******',
        // 微信支付对应的商户ID
        'mchid'   => '158......',
        // 微信支付对应的KEY , 在微信支付 > api 安全 获取
        'key'     => '******'
    ),

JSAPI 演示代码

# 控制器代码

<?php
class payController extends grace{
    // 首页控制器
    public function index(){
        // 如果沒有用户openID 数据则获取
        $openid = \getSession('userOpenid');
        if(empty($openid)){$this->getOpenID(); exit();}
    }

    // 获取 openID 函数
    protected function getOpenID(){
        $graceWeChat = new \phpGrace\tools\graceWeChat();
        $backUrl = 'http://您的域名.com/pay/loginBack';
        $graceWeChat->login($backUrl);
    }

    // 生成微信支付订单接口
    // 前端通过 js 请求访问此接口
    public function order(){
        /*
         * 微信支付后端示例代码
         * 模拟一个1元的支付信息,真实环境可以利用订单数据来产生下面的order数据
         */
        //模拟一个简单的订单信息
        $order = array(
            'id'         => mt_rand(111111111,999999999),     // 订单号码
            'price'      => 1           // 订单价格
        );
        //使用统一下单接口返回微信支付前端必须的信息
        $orderWxPay                  = array();
        $orderWxPay['body']         = '支付描述'; //支付描述
        //商户系统内部订单号,要求32个字符内
        $orderWxPay['out_trade_no'] = $order['id'];
        //总价,需要 * 100
        $orderWxPay['total_fee']    = $order['price'];
        //异步接收微信支付结果通知的回调地址
        $orderWxPay['notify_url']   = 'http://您的域名.com/pay/payback/';
        //客户的openid 公众号支付必须参数,通过登录即可获取
        $orderWxPay['openid']       = \getSession('userOpenid');
        //实例化微信支付对象
        $graceWeChat    = new \phpGrace\tools\graceWeChat();
        $graceWeChatPay = new \phpGrace\tools\graceWeChat\pay($graceWeChat);
        //生成订单并返回支付必须的信息
        $graceWeChatPay->createOrder($orderWxPay, 'JSAPI');
    }

    // 登录成功返回页面
    public function loginBack(){
        // 检查 url 参数
        if(empty($_GET['code']) || empty($_GET['state'])){exit('参数错误,请返回重试!E01');}
        // 检查 status 参数
        $wxLoginState = getSession('wxLoginState');
        if(empty($wxLoginState)){exit('参数错误,请重试!E02');}
        if($wxLoginState != $_GET['state']){exit('参数错误,请重试!E03');}
        // 获取用户信息
        $graceWeChat = new \phpGrace\tools\graceWeChat();
        $user        = $graceWeChat->loginBack();
        if(empty($user) || empty($user['openid'])){exit('登录失败');}
        //获取用户信息 [ 用户全部信息 对象形式]
        $user = $graceWeChat->getUser($user['openid']);
        // 利用 session 记录 openid
        \setSession('userOpenid', $user->openid);
        // 跳转回pay页面
        header('location:/pay/');
    }

    // 支付成功后微信支付服务器异步通知接口
    // 根据通知结果处理订单状态等后续工作
    public function payback(){
        $graceWeChat    = new \phpGrace\tools\graceWeChat();
        $graceWeChatPay = new \phpGrace\tools\graceWeChat\pay($graceWeChat);
        $res = $graceWeChatPay->payBack();
        // 将 res 数组与数据库内订单信息进行比对,比对后进行后续操作,如:更新订单、发送通知......
        file_put_contents('pay.txt', json_encode($res, JSON_UNESCAPED_UNICODE));
        echo '<xml> 
        <return_code><![CDATA[SUCCESS]]></return_code>
        <return_msg><![CDATA[OK]]></return_msg>
      </xml>';
    }
}

# 视图代码

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
</head>
<body>
<h1>pay Demo</h1>
<div style="padding:28px; padding-bottom:0px; line-height:28px; text-align:center;">
    点击按钮开始支付
</div>
<style>
    .button{width:150px; height:50px; line-height:50px;}
</style>
<div style="padding:28px;">
    <button type="button" class="button" id="btn1">支付</button>
</div>
<!-- 此处用于调试输出后端接口结果,上线后请删除调试功能 -->
<div id="res"></div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<?php
$graceWeChat = new \phpGrace\tools\graceWeChat();
$jsConfig    = $graceWeChat->getJsTicket();
?>
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script type="text/javascript">
wx.config({
    debug: false,
    appId: '<?php echo $graceWeChat->appId;?>',
    timestamp: <?php echo $jsConfig["timestamp"];?>,
    nonceStr: '<?php echo $jsConfig["nonceStr"];?>',
    signature: '<?php echo $jsConfig["signature"];?>',
    jsApiList: ['chooseWXPay']
});
</script>
<script type="text/javascript">
    $('#btn1').click(function(){
        $.getJSON(
            '/pay/order',
            function(res){
                console.log(res);
                $('#res').html(JSON.stringify(res));
                if(res.result_code == "FAIL"){
                    alert(res.err_code_des);
                    return false;
                }
                //发起微信支付
                WeixinJSBridge.invoke(
                    'getBrandWCPayRequest',
                    {
                        "appId"       : res.appId,
                        "timeStamp"   : res.timeStamp,
                        "nonceStr"    : res.nonceStr,
                        "package"     : res.package,
                        "signType"    : "MD5",
                        "paySign"     : res.paySign
                    },
                    function(res){
                        $('#res').html($('#res').html() + JSON.stringify(res));
                        if(res.err_msg == "get_brand_wcpay_request:ok"){
                            alert('支付成功,感谢您的支持!');
                            // jixu
                        }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                            alert('您取消了支付');
                        }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                            alert('支付失败');
                        }else{
                            alert(res.err_msg)
                        }
                    }
                );
                return;
            }
        );
    });
</script>
</body>
</html>

异步通知XML格式

<xml>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <return_msg><![CDATA[OK]]></return_msg>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <mch_id><![CDATA[1584666521]]></mch_id>
    <appid><![CDATA[******]]></appid>
    <openid><![CDATA[******]]></openid>
    <is_subscribe><![CDATA[Y]]></is_subscribe>
    <trade_type><![CDATA[JSAPI]]></trade_type>
    <trade_state><![CDATA[SUCCESS]]></trade_state>
    <bank_type><![CDATA[OTHERS]]></bank_type>
    <total_fee>1</total_fee>
    <fee_type><![CDATA[CNY]]></fee_type>
    <cash_fee>1</cash_fee>
    <cash_fee_type><![CDATA[CNY]]></cash_fee_type>
    <transaction_id><![CDATA[42000011690231041811]]></transaction_id>
    <out_trade_no><![CDATA[2519345]]></out_trade_no>
    <attach><![CDATA[]]></attach>
    <time_end><![CDATA[20210624153110]]></time_end>
    <trade_state_desc><![CDATA[支付成功]]></trade_state_desc>
    <nonce_str><![CDATA[h92NHICGlseZZ]]></nonce_str>
    <sign><![CDATA[1E877B00398C4FEBA483AC16795448]]></sign>
</xml>