Thinkphp3.2.3微信jsapi支付实例

分类: PHP实例 热度:107℃

第一步:微信官网下载demo实例

下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 

image.png

 我们改名为 wxpay 文件夹


第二步:配置微信公众号授权页面地址

image.png

第三步:配置微信商家后台配置jsapi授权目录

image.png


第四步:配置wxpay文件夹下 -> example -> WxPay.Config.php 文件

//=======【基本信息设置】=====================================
 /**
  * TODO: 修改这里配置为您自己申请的商户信息
  * 微信公众号信息配置
  * 
  * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
  * 
  * MCHID:商户号(必须配置,开户邮件中可查看)
  * 
  */
 public function GetAppId()
 {
 return '你的appid';
 }
 public function GetMerchantId()
 {
 return '商户号';
 }
 
 
//=======【商户密钥信息-需要业务方继承】===================================
    /*
    * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置), 请妥善保管, 避免密钥泄露
    * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
    * 
    * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), 请妥善保管, 避免密钥泄露
    * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
    * @var string
    */
    public function GetKey()
    {
    return '你的微信公众号Key';
    }
    public function GetAppSecret()
    {
    return '你的微信公众号AppSecret';
    }

以上配置已经完成。

本人使用TP框架3.2.3来演示实例

第五步:把wxpay文件夹放到tp框架第三方类库下 地址如下

ThinkPHP/Library/Vendor/

新建一个php页面命名为 WxController.class.php

<?php
namespace HomeController;
use ThinkController;
require_cache(LIB_PATH."Vendor/wxpay/lib/WxPay.Api.php");
require_cache(LIB_PATH."Vendor/wxpay/example/WxPay.JsApiPay.php");
require_cache(LIB_PATH."Vendor/wxpay/example/WxPay.Config.php");
require_cache(LIB_PATH."Vendor/wxpay/example/log.php");
class WxController extends Controller { 


    public function index(){


         $this->display();   
   }   
    // 支付处理    
    public function wxpay(){
        
        $tools = new JsApiPay();
        $openId = $tools->GetOpenid();
        //②、统一下单
        $input = new WxPayUnifiedOrder();
        $input->SetBody("test");
        $input->SetAttach("test");
        $input->SetOut_trade_no("sdkphp".date("YmdHis"));
        $input->SetTotal_fee("99");
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("test");
        $input->SetNotify_url("http://www.jusucai.cn/Notify/index");
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($openId);
        $config = new WxPayConfig();
        $order = WxPayApi::unifiedOrder($config, $input);
        echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
        $this->printf_info($order);
        $jsApiParameters = $tools->GetJsApiParameters($order);
        $this->assign('jsApiParameters' , $jsApiParameters);
        $this->display();
    }

    public function printf_info($data)
    {
        foreach($data as $key=>$value){
            echo "<font color='#00ff55;'>$key</font> :  ".htmlspecialchars($value, ENT_QUOTES)." <br/>";
        }
    }


 }

对应的html页面 Wx控制下的wxpay方法

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>微信支付样例-支付</title>


    <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/>
<div align="center">
    <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>



    <script type="text/javascript">
        //调用微信JS api 支付
        function jsApiCall()
        {
            WeixinJSBridge.invoke(
                'getBrandWCPayRequest',
                {$jsApiParameters},
            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:ok"){ 
                 alert("支付成功!"); 
                 // window.location.href="http://m.blog.csdn.net/article/details?id=72765676" rel="external nofollow" ; 
                }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ 
                    alert("用户取消支付!"); 
                }else{ 
                    alert("支付失败!"); 
                }


            }
        );
        }

        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/>

</body>
</html>

这时候访问 你的地址例如 www.*******.cn/Wx/wxpay

image.png   image.png

注意:成功会弹出 OK 但是支付成功如何 业务逻辑处理 这里要说我们的回调地址

   我的回调地址     $input->SetNotify_url("http://www.jusucai.cn/Notify/index");

第六步:新建回调PHP文件

<?php
/**
 * Date: 2019/3/5
 * Time: 16:46
 */
namespace HomeController;
use ThinkController;
require_cache(LIB_PATH."Vendor/wxpay/lib/WxPay.Api.php");
require_cache(LIB_PATH."Vendor/wxpay/lib/WxPay.Notify.php");
require_cache(LIB_PATH."Vendor/wxpay/example/WxPay.Config.php");
require_cache(LIB_PATH."Vendor/wxpay/example/log.php");
class NotifyController extends Controller {

    private $WxPayNotifyReply;

    private $wxpageconfig = null;

    public function __construct()
    {
        parent::__construct();
        $this->wxpageconfig = new WxPayConfig();;
        $this->WxPayNotifyReply = new WxPayNotifyReply();
    }

    public function index(){
        $msg = "OK";
        $config = $this->wxpageconfig;
        //当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败
        $result = WxpayApi::notify($config, array($this, 'NotifyCallBack'), $msg);
        if($result == false){
            $this->WxPayNotifyReply->SetReturn_code("FAIL");
            $this->WxPayNotifyReply->SetReturn_msg($msg);
            $this->ReplyNotify(false);
            return;
        } else {
            //该分支在成功回调到NotifyCallBack方法,处理完成之后流程
            $this->WxPayNotifyReply->SetReturn_code("SUCCESS");
            $this->WxPayNotifyReply->SetReturn_msg("OK");
        }
        $this->ReplyNotify(false);
    }


    /**
     *
     * 回调方法入口,子类可重写该方法
    //TODO 1、进行参数校验
    //TODO 2、进行签名验证
    //TODO 3、处理业务逻辑
     * 注意:
     * 1、微信回调超时时间为2s,建议用户使用异步处理流程,确认成功之后立刻回复微信服务器
     * 2、微信服务器在调用失败或者接到回包为非确认包的时候,会发起重试,需确保你的回调是可以重入
     * @param WxPayNotifyResults $objData 回调解释出的参数
     * @param WxPayConfigInterface $config
     * @param string $msg 如果回调处理失败,可以将错误信息输出到该方法
     * @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
     */
    public function NotifyProcess($objData, $config, &$msg)
    {
        $data = $objData->GetValues();
        //TODO 1、进行参数校验
        if(!array_key_exists("return_code", $data)
            ||(array_key_exists("return_code", $data) && $data['return_code'] != "SUCCESS")) {
            //TODO失败,不是支付成功的通知
            //如果有需要可以做失败时候的一些清理处理,并且做一些监控
            $msg = "异常异常";
            return false;
        }
        if(!array_key_exists("transaction_id", $data)){
            $msg = "输入参数不正确";
            return false;
        }

        //TODO 2、进行签名验证
        try {
            $checkResult = $objData->CheckSign($config);
            if($checkResult == false){
                //签名错误
                Log::ERROR("签名错误...");
                return false;
            }
        } catch(Exception $e) {
            Log::ERROR(json_encode($e));
        }

        //查询订单,判断订单真实性
        if(!$this->Queryorder($data["transaction_id"])){
            $msg = "订单查询失败";
            return false;
        }

        $order_id = $data['out_trade_no'];//这个是订单id
        //TODO 3、处理业务逻辑
        //可以根据订单号查询数据库 更改订单支付状态 比如
        
        // 更改数据库支付状态
        M('orders')->where("order_no = '{$order_id}' ")->save(array('pay_status'=>1));

        return true;
    }

    //查询订单
    public function Queryorder($transaction_id)
    {
        $input = new WxPayOrderQuery();
        $input->SetTransaction_id($transaction_id);
        $config = new WxPayConfig();
        $result = WxPayApi::orderQuery($config, $input);
        if(array_key_exists("return_code", $result)
            && array_key_exists("result_code", $result)
            && $result["return_code"] == "SUCCESS"
            && $result["result_code"] == "SUCCESS")
        {
            return true;
        }
        return false;
    }


    /**
     *
     * 业务可以继承该方法,打印XML方便定位.
     * @param string $xmlData 返回的xml参数
     *
     **/
    public function LogAfterProcess($xmlData)
    {
        return;
    }

    /**
     *
     * notify回调方法,该方法中需要赋值需要输出的参数,不可重写
     * @param array $data
     * @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
     */
    final public function NotifyCallBack($data)
    {
        $msg = "OK";
        $result = $this->NotifyProcess($data, $this->wxpageconfig, $msg);

        if($result == true){
            $this->WxPayNotifyReply->SetReturn_code("SUCCESS");
            $this->WxPayNotifyReply->SetReturn_msg("OK");
        } else {
            $this->WxPayNotifyReply->SetReturn_code("FAIL");
            $this->WxPayNotifyReply->SetReturn_msg($msg);
        }
        return $result;
    }

    /**
     *
     * 回复通知
     * @param bool $needSign 是否需要签名输出
     */
    final private function ReplyNotify($needSign = true)
    {
        //如果需要签名
        if($needSign == true &&
            $this->WxPayNotifyReply->GetReturn_code() == "SUCCESS")
        {
            $this->$this->WxPayNotifyReply($this->config);
        }

        $xml = $this->WxPayNotifyReply->ToXml();
        $this->LogAfterProcess($xml);
        WxpayApi::replyNotify($xml);
    }

}

 回调PHP页面只处理 NotifyProcess 方法

NotifyProcess 方法即可

在业务逻辑下处理订单支付状态即可
// 更改数据库支付状态
M('orders')->where("order_no = '{$order_id}' ")->save(array('pay_status'=>1));

然后查看我们数据库订单记录是否支付成功

image.png

到这里我们的thinkphp3.2.3微信 jsapi支付已经成功了。

实例源码 

wxpay.zip


转载请注明:李洋博客 » Thinkphp3.2.3微信jsapi支付实例

一键分享:0