TP5.0微信支付V3扫码支付开发记录【没用官方SDK】

前端代码

1. 前端发起代码请求,去后台换取code_url.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>微信支付</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    {include file="Common/pcmeta" /}
    <script type="text/javascript" src="//static.runoob.com/assets/qrcode/qrcode.min.js"></script>
  </head>

  <body>
    <!-- 中间频道 -->
    <div class="consult">
      <div class="wxLogo">
        <img src="__STATIC__/pc/./image/icon/wxlogo.png" alt="">
      </div>
      <hr />

      <div class="payTips">
        <div class="payTips_a">
          <span>服务名称:</span>{$cont.server}
        </div>

        <div class="payTips_a">
          <span>服务价格:</span>{$cont.salary} 元
        </div>

        <div class="payTips_a">
          <span>订单编号:</span><input type="text" value="{$cont.key}" id="orderNum" readonly>
        </div>
<!--        接收二维码地址-->
        <input type="hidden" value="{$imgStr}" id="codeurl">
        <input type="hidden" value="{$cont.id}" id="orderid">
        <input type="hidden" value="{$cont.server}" id="server">

      </div>

      <div class="qrBox">
        <div class="qrBox_title">
          <img src="__STATIC__/pc/./image/icon/wxlogo.png" alt="">
        </div>
        <div id="qrcode" class="qrcodeimg"></div>
        <div class="qrbox_tips" id="tipsMess">请使用手机微信扫一扫付款</div>
      </div>
    </div>

    <script>
      let qrCode = new QRCode(document.getElementById("qrcode"),{
        width:200,
        height:200
      });

      function makeCode()
      {
        var elText = document.getElementById("codeurl");
        if (!elText.value) {
          layer.msg("未获取到支付二维码");
          elText.focus();
          return;
        }
        qrCode.makeCode(elText.value);
      }

      makeCode();

    </script>

<!--  支付回调-->
    <script>
      let orderNum = document.getElementById("orderNum").value;
      let id     = $('#orderid').val();
      let server = $('#server').val();
      let i = setInterval(getNotifiy,2000);
      function getNotifiy()
      {
        $.ajax({
          type:'post',
          data:{orderNum:orderNum},
          url:"{:url('../patient/pay/selPayState')}",
          dataType:'json',
          success:function (data)
          {
            if(data.trade_state_desc === '支付成功')
            {
              clearInterval(i);
              location.href="{:url('../patient/pay/payment')}?trader="+data.out_trade_no+'&id='+id+'&transaction='+data.transaction_id+'&amount='+data.amount.total+'&server='+server;
            }

          },
          error:function ()
          {
            layer.msg('请求失败');
          }
        })
      }
    </script>
  </body>
</html>

2.控制器代码

	const appid = '';//公众号应用APPID
    const mchid = '';//直联商户号
    private $nocesStr;

    public function __construct(){
        //使用父类的构造函数,也就是调用Controller类的构造函数
        parent::__construct();
        $str   = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $key = "";
        for($i=0;$i<strlen($str)-4;$i++)
        {
            $key .= $str{mt_rand(0,32)};    //生成php随机数
        }
        $this -> nocesStr = $key;
    }

    //微信支付展示页
    public function index()
    {
        $key = $this -> nocesStr;
        $id     = $_GET['id'];
        $salary = (float)$_GET['salary']*100;
        $server = $_GET['server'];
        $arr    = [
            'id' =>$id,
            'salary'=>$salary/100,
            'server'=>$server,
            'key'   =>$key
        ];
        $url    = 'https://xxxxxx.com/patient/notify';//回调链接
        $result = $this -> wxPay($server,$url,$salary,$key);
        $code_url = str_replace("}",'',str_replace('"','',substr($result,12)));

        $this -> assign('cont',$arr);
        $this -> assign('imgStr',$code_url);

        return $this -> fetch('Pc/pay');
    }

    /*
     * 微信支付拼接json请求字符串
     */
    public function wxPay($descr,$url,$salary,$key)
    {

        $arr = [
            'mchid' => self::mchid,//商户号
            'out_trade_no' => $key,//商户订单号
            'appid' => self::appid,//appID
            'description' => $descr,
            'notify_url' => $url,
            'amount'=>['total' => $salary,'currency'=>'CNY'],
        ];

        $jsonStr = json_encode($arr);
        $result  = $this -> toPay($jsonStr,$key);
        return $result;
    }

    /*
     * 调用接口
     */
    public function toPay($str,$key)
    {
        $requestUrl = 'https://api.mch.weixin.qq.com/v3/pay/transactions/native';//Native支付请求地址
        $message = wxPay_native($key,$str);

        $headers = ['Accept: application/json',
            'Content-Type: application/json; charset=utf-8',
            'User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)',
            $message
        ];
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $requestUrl);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $str);
        curl_setopt($curl, CURLOPT_HTTPHEADER,$headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $codeUrl = curl_exec($curl);
        curl_close($curl);
        return $codeUrl;
    }

3.公共方法,主要为调起支付进行加密

//微信扫码支付
function wxPay_native($key,$jsonStr)
{
    $method = "POST";
    $URL    = "/v3/pay/transactions/native";//对应要请求的接口域名后的所有参数
    $time   = time();
    $reStr  = $key;//请求支付所用的随机字符串
    $body   = $jsonStr;//请求报文【请求接口所用的所有参数】
    $mch_private_key = openssl_get_privatekey(file_get_contents("https://xxxx.com/cert/apiclient_key.pem"));//用微信支付提供的秘钥进行加密
    $message = $method."\n". $URL."\n". $time."\n". $reStr."\n". $body."\n";//拼接加密字符串

    openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');//进行加密
    $base    = base64_encode($raw_sign);

    $schema = "WECHATPAY2-SHA256-RSA2048";
    $endStr_a  = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', mchid, $reStr, $time, "69DB9A9B394F307DB87163DB52D579DE29765C30", $base);
    return 'Authorization:'.$schema.' '.$endStr_a;//返回请求头用于上方发起支付的请求头
}

4.将获取回来的url_code返回到支付页面进行转化为二维码,用的qrcodeJS进行转化。然后轮训2秒轮训微信支付查询接口【也需要进行加密】进行判断用户是否已经支付进行下一步逻辑操作 核心代码如下:

<script>
      let qrCode = new QRCode(document.getElementById("qrcode"),{
        width:200,
        height:200
      });

      function makeCode()
      {
        var elText = document.getElementById("codeurl");
        if (!elText.value) {
          layer.msg("未获取到支付二维码");
          elText.focus();
          return;
        }
        qrCode.makeCode(elText.value);
      }

      makeCode();

    </script>

<!--  支付回调-->
    <script>
      let orderNum = document.getElementById("orderNum").value;
      let id     = $('#orderid').val();
      let server = $('#server').val();
      let i = setInterval(getNotifiy,2000);
      function getNotifiy()
      {
        $.ajax({
          type:'post',
          data:{orderNum:orderNum},
          url:"{:url('../patient/pay/selPayState')}",
          dataType:'json',
          success:function (data)
          {
            if(data.trade_state_desc === '支付成功')
            {
              clearInterval(i);
              location.href="{:url('../patient/pay/payment')}?trader="+data.out_trade_no+'&id='+id+'&transaction='+data.transaction_id+'&amount='+data.amount.total+'&server='+server;
            }

          },
          error:function ()
          {
            layer.msg('请求失败');
          }
        })
      }
    </script>

控制器代码

*
     * 查询是否支付完成
     */
    public function selPayState()
    {
        header("Access-Control-Allow-Origin:*");
        header("Access-Control-Allow-Methods:GET,POST");
        $key = $this -> nocesStr;
        $orderNum = $_POST['orderNum'];
        $url      = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/".$orderNum.'?mchid='.self::mchid;
        $result   = selPayState($url,$key,$orderNum);
        return $result;
    }

    //支付成功进行入库记录
    public function payment()
    {
        $sess = Session::get('login');
        $customer   = $sess['h_name'];
        $customerid = $sess['h_customerid'];
        $phone      = $sess['h_phone'];
        $id         = $_GET['id'];
        $trader     = $_GET['trader'];
        $transaction= $_GET['transaction'];
        $amount     = $_GET['amount']/100;
        $server     = $_GET['server'];
        $arr = [
            'h_customer' => $customer,
            'h_customerid' => $customerid,
            'h_phone' => $phone,
            'h_trader' => $trader,
            'h_transaction' => $transaction,
            'h_total' => $amount,
            'h_server' =>$server,
            'h_date' => Date('Y-m-d H:i:s')
        ];
        $insert = Db::name('payment') -> insert($arr);
        if(!$insert)
        {
            return json('error:网络环境错误');
        }
        $changeState = Db::name('operation') -> where('h_oid',$id)
                                             -> where('h_opercode',$customerid)
                                             -> update(['h_paystate'=>'2']);
        if(!$changeState)
        {
            return json('error:网络环境错误');
        }
        $this->assign('cont',$arr);

        return $this -> fetch('Pc/paySuccess');

加密公共函数

//查询支付状态
function selPayState($url,$key,$orderNum)
{
    header("Access-Control-Allow-Origin:*");
    header("Access-Control-Allow-Methods:GET,POST");
    $method = "GET";
    $URL    = "/v3/pay/transactions/out-trade-no/".$orderNum."?mchid=".mchid;
    $time   = time();
    $reStr  = $key;
    $body   = "";
    $mch_private_key = openssl_get_privatekey(file_get_contents("https://xxx.com/cert/apiclient_key.pem"));
    $message = $method."\n". $URL."\n". $time."\n". $reStr."\n". $body."\n";
    openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
    $base    = base64_encode($raw_sign);
    $schema  = "WECHATPAY2-SHA256-RSA2048";
    $endStr_a  = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', mchid, $reStr, $time, "69DB9A9B394F307DB87163DB52D579DE29765C30", $base);
    $sign_str =  'Authorization:'.$schema.' '.$endStr_a;

    $headers = ['Accept: application/json',
        'Content-Type: application/json; charset=utf-8',
        'User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)',
        $sign_str
    ];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
    $output = curl_exec($ch);
    curl_close($ch);
    $output = json_decode($output,true);
    return $output;

总结

微信支付,整体文档写的并非是按部就班,我们应该先从指引文档->基础支付里选择要接入的接口,认真仔细的去阅读,可以用官方的SDK 也可以自行封装。自行封装主要去看下签名生成,根据文档提示一步一步进行封装即可。
整体来说,V3版本微信支付,比V2接入更简单一些了,全部数据交互用到json,而非XML。对于新手来说还是比较好的!加密过程是核心。后期更新一下jsapi的接入过程,其实和native一样,只不过是多了一个参数需要获取到支付用户的openid。

如果对于小白本文有帮助的话留个赞,大佬的话也不要嫌弃小弟的代码毕竟都是自学嘛~~bye~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值