微信支付demo


這里開發時使用的是thinkphp5.1

1.直接喚起微信支付

<?php
namespace app\index\controller;

use wechatpay\lib\WxPayApi;
use wechatpay\lib\WxPayUnifiedOrder;
use wechatpay\example\JsApiPay;
use wechatpay\example\WxPayConfig;
use think\facade\Env;

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;
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM