zoukankan      html  css  js  c++  java
  • 微信支付demo

    这里开发时使用的是thinkphp5.1

    1.直接唤起微信支付

    <?php
    namespace appindexcontroller;
    
    use wechatpaylibWxPayApi;
    use wechatpaylibWxPayUnifiedOrder;
    use wechatpayexampleJsApiPay;
    use wechatpayexampleWxPayConfig;
    use thinkfacadeEnv;
    
    class Pay
    {
        /*
        1、交易金额
        交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数。对账单中的交易金额单位为【元】。
    
        外币交易的支付金额精确到币种的最小单位,参数值不能带小数点。
    
        2、交易类型
        JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里
    
        MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口
    
        3、货币类型
        货币类型的取值列表:
    
        CNY:人民币
    
        4、时间
        标准北京时间,时区为东八区;如果商户的系统时间为非标准北京时间。参数值必须根据商户系统所在时区先换算成标准北京时间, 例如商户所在地为0时区的伦敦,当地时间为2014年11月11日0时0分0秒,换算成北京时间为2014年11月11日8时0分0秒。
    
        5、时间戳
        标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数。注意:部分系统取到的值为毫秒级,需要转换成秒(10位数字)。
    
        6、商户订单号
        商户支付的订单号由商户自定义生成,仅支持使用字母、数字、中划线-、下划线_、竖线|、星号*这些英文半角字符的组合,请勿使用汉字或全角等特殊字符。微信支付要求商户订单号保持唯一性(建议根据当前系统时间加随机序列来生成订单号)。重新发起一笔支付要使用原订单号,避免重复支付;已支付过或已调用关单、撤销(请见后文的API列表)的订单号不能重新发起支付。
        */
    
    
        /**
         * 微信支付调用
         * @author ffx
         * @param int $userId 用户id
         * @param float $money 金额
         * @param int $type 支付类型(1充值,2订单支付)
         * @param string $body 显示title,提示头信息
         * @param string $backUrl 回调地址(/index/pay/wxPayBack)
         * @param string $addition 附加参数(微信回调时原样返回)
         * @return bool|mixed
         */
        public function wxPay($userId,$money,$type,$body,$backUrl,$addition = '')
        {
            $out_trade_no = self::getOrderNo();
            $wxchid = config('wechat.wxmchid');
            $wxAppId = config('wechat.paywxAppId');
    
            //微信支付sdk中的文件
            include_once EXTEND_PATH."wechatpay/lib/WxPay.Api.php";
            include_once EXTEND_PATH."wechatpay/example/WxPay.JsApiPay.php";
    
            $total_money = floor(sprintf("%0.3f",$money)*100);
            if(!$total_money || $total_money <= 0){
                return ['code'=>100001,'message'=>"支付金额小于0"];
            }
            if($_SERVER["REQUEST_SCHEME"] == "http"){
                $notify_url  = 'http://'.$_SERVER['HTTP_HOST'].$backUrl;
            }else{
                $notify_url  = 'https://'.$_SERVER['HTTP_HOST'].$backUrl;
            }
    
            //此处查询的是登录时存起来的openid
            $openid = Db::name('member')->where('id',$userId)->value('openid');
            $input = new WxPayUnifiedOrder();
    
            $input->SetAppid($wxAppId);
            $input->SetMch_id($wxchid); //商户号
            $input->SetAttach($addition); //附加参数
            $nonceStr = self::createNonceStr();
            $input->SetNonce_str($nonceStr);//自定义随机字符串
            $input->SetBody($body);//
            $input->SetOut_trade_no($out_trade_no);//订单号,自己建
            $input->SetTotal_fee($total_money);//金钱
            $input->SetSpbill_create_ip($this->getIP());//客户端ip
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));//过期时间
            $input->SetNotify_url($notify_url);//回调的接口地址
            $input->SetTrade_type("JSAPI");//支付类型
            $input->SetOpenid($openid);
    
            //此处两个是微信支付的sdk的类
            $WxPayApi = new WxPayApi();
            $config = new WxPayConfig();
    
            $response = $WxPayApi->unifiedOrder($config,$input);//预创建订单
    
            //写入支付记录表(业务逻辑处理)
            $res = $this->insertWxPayLog($userId,$out_trade_no,$money,$type,0);
            if(!$res){
                return false;
            }
    
            if($response['result_code']=='SUCCESS' && $response['return_code']=='SUCCESS' && $response['return_msg']=='OK') {
                $tools = new JsApiPay();
                $response['nonce_str'] = $nonceStr;
                $jsApiParameters = $tools->GetJsApiParameters($response);
                return json_decode($jsApiParameters);
    
                //$jsApiParameters示例
                //{"appId":"wx194a1075c8bca3d9","nonceStr":"4tmc7nttscu5w6u6cqbxlgvum4qs6p8y","package":"prepay_id=wx05155440194924091e0efc912670185750","signType":"MD5","timeStamp":"1541404480","paySign":"CD4DE57A6B5B2B5418B5F07536C4DF10"}
    
                //输出直接唤起支付
    //            $str = "<html><body></body></html>";
    //
    //            $str .='<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></head><body>';
    //
    //            $str .= "<script>function onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest',$jsApiParameters)}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></body></html>";
    //
    //            echo $str;exit;
    
            }else{
                return false;
            }
    
        }
    
        /**
         * 余额支付回调
         * @author ffx
         *
         */
        function amountPayBack()
        {
            $xml = file_get_contents('php://input');
            $xmlJson = json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA));
            $arr = json_decode($xmlJson, true);
    
            //此处注释暂未用到
            /* //用户http_build_query()将数据转成URL键值对形式
             $sign = http_build_query($arr);
             //md5处理
             $sign = md5($sign);
             //转大写
             $sign = strtoupper($sign);
             //验签名。默认支持MD5
             if($sign === $arr['sign']) {
                 // 校验返回的订单金额是否与商户侧的订单金额一致。修改订单表中的支付状态。
             }
             $return = ['return_code'=>'SUCCESS','return_msg'=>'OK'];
             $xml = '<xml>';
             foreach($return as $k=>$v){
                 $xml.='<'.$k.'><![CDATA['.$v.']]></'.$k.'>';
             }
             $xml.='</xml>';*/
    
            $out_trade_no=$arr['out_trade_no']; //订单号
    
            //判断金额
            $total_fee=$arr['total_fee']/100*10000; //回调回来的xml文件中金额是以分为单位的
            $money = Db::name('recharge_log')->where('out_trade_no',$out_trade_no)->value('money');
            if($money != $total_fee){
                return;
            }
    
            $result_code=$arr['result_code']; //状态
            if($result_code=='SUCCESS'){
                //处理数据库操作
                $post = [
                    'out_trade_no'=>$out_trade_no,
                    'total_fee'=>$arr['total_fee'] //微信实际收到金额(分为单位)
                ];
                //处理业务逻辑
                $res = $this->amountPayBackLogic($xmlJson,$post,1,$money);
                if($res['code'] == 0){
                    echo 'SUCCESS'; //返回成功给微信端 一定要带上不然微信会一直回调8次
                    exit;
                }
            }else{
                //失败
                return;
            }
        }
    
        /**
         * 获取随机字符串
         * @author ffx
         * @param int $length 长度
         * @return string
         */
        public static function createNonceStr($length = 16)
        {
            $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            $str = '';
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            }
            return $str;
        }
    
        /**
         * 获取订单号
         * @author ffx
         * @return string
         */
        public static function getOrderNo()
        {
            $outTradeNo = time() . rand(1000, 9999);
            return $outTradeNo;
        }
    
        /**
         * @purpose 获取请求来源的ip
         * @author ffx
         * @return mixed
         */
        function getIp()
        {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip = $_SERVER['HTTP_CLIENT_IP'];
            } else {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
            $ip_arr = explode(',', $ip);
            return $ip_arr[0];
        }
    
    
    }

    2.生成二维码支付

    回调和唤起支付一样

    /**
         * 微信支付调用
         * @author ffx
         * @param int $userId 用户id
         * @param float $money 金额
         * @param string $body 显示title,提示头信息
         * @param string $backUrl 回调地址(/v1/pay/wxPayBack)
         * @param string $addition 附加参数(微信回调时原样返回)
         * @return bool
         */
        public function wxPayErWeiMa($userId,$money,$body,$backUrl,$addition = '')
        {
            $out_trade_no = self::getOrderNo();
            $total_money = $money;
    
            include_once EXTEND_PATH."wxpay/lib/WxPay.Api.php";
            include_once EXTEND_PATH."wxpay/example/WxPay.JsApiPay.php";
            include_once EXTEND_PATH."wxpay/example/WxPay.NativePay.php";
    
            $total_money = floor(sprintf("%0.3f",$total_money)*100);
            if(!$total_money || $total_money <= 0){
                return ['code'=>100001,'message'=>"支付金额小于0"];
            }
            $notify_url  = 'http://'.$_SERVER['HTTP_HOST'].$backUrl;
    
            $wxPayConfig = Db::name('user_wxpay_config')
                ->alias('c')
                ->join('member m','m.admin_user=c.admin_user')
                ->where('m.id', $userId)
                ->where('c.status', 1)
                ->field('c.*')
                ->order('update_time','desc')
                ->find();
            if(empty($wxPayConfig)){
                return false;
            }
    
            if(empty($body)){
                $body = $wxPayConfig['body'];
            }
    
            $wxchid = $wxPayConfig['mac_id'];
            $wxAppId = $wxPayConfig['appid'];
            $wxAppSecret = $wxPayConfig['app_secret'];
            $wxKey = $wxPayConfig['key'];
    
            $config = new WxPayConfig();
            $config->SetAppSecret($wxAppSecret);
            $config->SetKey($wxKey);
            $config->SetAppId1($wxAppId);
            $config->SetMerchantId1($wxchid);
    
            $input = new WxPayUnifiedOrder();
            $input->SetBody($body);
            $input->SetAttach($addition); //附加参数
            $input->SetOut_trade_no($out_trade_no); //订单号,自己建
            $input->SetTotal_fee($total_money);//金钱
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600)); //过期时间
            $input->SetGoods_tag("test");
            $input->SetNotify_url($notify_url); //回调的接口地址
            $input->SetTrade_type("NATIVE"); //支付类型(二维码)
            $input->SetProduct_id("123456789");
    
            //写入支付记录表
            $res = $this->insertRechargeLog($userId,$out_trade_no,$money,0,'wxpay');
            if(!$res){
                return false;
            }
            $notify = new NativePay();
            $result = $notify->GetPayUrl($input);
    
            if(isset($result["code_url"]) && !empty($result["code_url"])){
                require_once './../extend/wxpay/example/phpqrcode/phpqrcode.php';
                $url = urldecode($result['code_url']);
                if(substr($url, 0, 6) == "weixin"){
                    QRcode::png($url);
                }else{
                    header('HTTP/1.1 404 Not Found');
                }
            }else{
                return false;
            }
        }
  • 相关阅读:
    DataGridView中DataGridViewComDaboBoxColumn控件点击一次即可显示下拉菜单
    Django2.X报错-------ModuleNotFoundError: No module named 'django.core.urlresolvers'
    C#控件——批量化隐藏或显示同类型控件
    Python——Django运行问题
    关于VS2010 在设计窗口时控件消失问题
    DataGridView操作小记(1)
    c#_生成图片式验证码
    日常杂记——C#验证码
    DataGridView添加的数据最后一步无法生效的问题。
    request.getRequestDispatcher().forward(request,response)和response.sendRedirect()的区别
  • 原文地址:https://www.cnblogs.com/yangjiayu/p/11176698.html
Copyright © 2011-2022 走看看