php对接微信扫码支付

申请商户号与服务号

可使用公司营业执照或个体工商户申请

微信商户平台(申请商户号)(微信支付审核 需要交300块钱)

https://pay.weixin.qq.com/index.php

微信公众平台(申请服务号)

https://mp.weixin.qq.com/

设置配置

商户号与服务号要先绑定
在这里插入图片描述

APPID:绑定支付的APPID

在这里插入图片描述

MCHID:商户号

在这里插入图片描述

KEY:商户支付密钥

登录商户品台自行设置,设置地址:https://pay.weixin.qq.com/core/cert/api_cert
可使用 http://suijimimashengcheng.51240.com 生成32位密码
在这里插入图片描述

APPSECRET:公众帐号secert

登录公众平台进入开发者中心可设置https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
在这里插入图片描述

登录微信商户平台后下载配置文件 apiclient_cert.pem 和 apiclient_key.pem

在这里插入图片描述

回调解密密钥

在这里插入图片描述

回调地址设置

在这里插入图片描述

官网支付demo下载

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

进行对接(使用Thinkphp5.1)

前台操作

<!DOCTYPE html>
<html>

<head>
	<title>{$user_login} - 支付充值</title>
	<meta name="keywords" content="" />
	<meta name="description" content="">
	<include file="public@head" />
</head>

<body class="body-white" id="top">
	<include file="public@nav" />

	<div class="container tc-main">
		<div class="row">
			<div class="col-md-3">
				<include file="public@usernav" />
			</div>
			<div class="col-md-9">
				<div class="tabs">
					<ul class="nav nav-tabs">
						<li class="active"><a href="#one" data-toggle="tab"><i class="fa fa-edit"></i> 支付充值</a></li>
					</ul>
					<div class="tab-content">
						<div class="tab-pane active" id="one">
							<br>
							<form class="js-ajax-form" method="post">
								<div class="form-group">

									<label for="input-sex">支付方式</label>
									<div>
										<div>微信支付<input type="radio" name="type" value="1" checked></div>
										<div>支付宝支付<input type="radio" name="type" value="2"></div>
									</div>

								</div>
								<div class="form-group">
									<label for="input-birthday">支付金额</label>
									<input class="form-control" type="number" name="money" value="0.01">
								</div>
								<div class="form-group">
									<input type="button" id="pay" class="btn btn-primary js-ajax-submit" value="确定">
								</div>
								<div id="pay_bolck" style="display: none;">
									<div id="pay_qrcode"></div>
									<span id="pay_text"></span>
								</div>
							</form>
						</div>
					</div>
				</div>
			</div>
		</div>
		<include file="public@footer" />
	</div>
	<!-- /container -->
	<include file="public@scripts" />
	<script src="https://cdn.bootcss.com/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
	<script>


		var out_trade_no = '';
		$('#pay').click(function (e) {
			$.ajax({
				type: "method",
				url: "{:url('pay')}",
				data: $("form").serialize(),
				method: "POST",
				dataType: "json",
				success: function (response) {
					var type = $("input:radio[name=type]:checked").val();
					if (type == 1) {
						$("#pay_bolck").css('display', 'block');
						$("#pay_qrcode").html('');
						out_trade_no = response.out_trade_no;
						$("#pay_qrcode").qrcode({
							width: 200,
							height: 200,
							text: response.url,
							// background:,//背景色,
							// foreground://前景色
						})
						$("#pay_text").text("打开微信,扫描二维码支付");
					}
				}
			});
		});


		//轮询订单状态
		$(document).ready(function () {
			setInterval("ajaxstatus()", 3000);
		});

		function ajaxstatus() {
			if (out_trade_no != '') {
				$.ajax({
					url: "{:url('payFind')}?out_trade_no=" + out_trade_no,
					type: "POST",
					dataType: "json",
					data: "",
					success: function (data) {
						if (data.code == 1) { //订单状态为1表示支付成功
							window.location.href = "/"; //页面跳转
						}
					},
					error: function () {
						alert("请求订单状态出错");
					}
				});
			}
		}

	</script>
</body>

</html>

接口扩展文件配置

从官方示例demo中拿出这些文件丢入thinkphp框架中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
require_once路径需修改

填入各项配置 加密选择MD5

	public function GetSignType()
	{
		return "MD5";
	}

扩展示例文件
链接:https://pan.baidu.com/s/1wQ8r17PhDYcQ-OWvRjWHdQ
提取码:0sb4

支付操作

入口文件index.php中加入常量配置
在这里插入图片描述

// 支付目录
define('PAY_PATH', CMF_ROOT . 'extend/Library/');
/**
 * 支付充值页面
 * 
 */
//$result返回的内容 
// array(10) {
//     ["appid"] => string(18) "XXXX"
//     ["code_url"] => string(35) "weixin://wxpay/bizpayurl?pr=XXXX"
//     ["mch_id"] => string(10) "XXX"
//     ["nonce_str"] => string(16) "XXX"
//     ["prepay_id"] => string(36) "XXXX"
//     ["result_code"] => string(7) "SUCCESS"
//     ["return_code"] => string(7) "SUCCESS"
//     ["return_msg"] => string(2) "OK"
//     ["sign"] => string(64) "XXXXX"
//     ["trade_type"] => string(6) "NATIVE"
//   }
public function pay()
{
    if ($this->request->isPost()) {
        //1微信 2支付宝
        $type = $this->request->param('type', 0, 'intval');
        //充值金额
        $money = $this->request->param('money', 0, 'floatval');

        if ($type == 1) {

            require PAY_PATH . '/wx_pay/WxPay.Api.php'; //引入微信支付
            $input = new \WxPayUnifiedOrder(); //统一下单
            $config = new \WxPayConfig(); //配置参数

            //$paymoney = input('post.paymoney'); //支付金额
            $paymoney = $money; //金额
            $out_trade_no = 'WXPAY' . date("YmdHis"); //商户订单号(自定义)
            $goods_name = '扫码支付' . $paymoney . '元'; //商品名称(自定义)
            $input->SetBody($goods_name);
            $input->SetAttach($goods_name);
            $input->SetOut_trade_no($out_trade_no);
            $input->SetTotal_fee($paymoney * 100); //金额乘以100
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetGoods_tag("test");
            $input->SetNotify_url("http://www.XXXX.com/common/third/paycallback"); //回调地址
            $input->SetTrade_type("NATIVE");
            $input->SetProduct_id("123456789"); //商品id

            $result = \WxPayApi::unifiedOrder($config, $input);
            // dump($result);exit;
            if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
                $url = $result["code_url"];
                $data = [
                    'uid'          => cmf_get_current_user_id(),
                    'total_fee'    => $paymoney,
                    'out_trade_no' => $out_trade_no,               //微信交易单号
                    'create_time'  => time(),                       //创建时间
                    'type'         => 1                            //微信支付
                ];
                //创建订单
                DB::name('recharge')->insert($data);

                return [
                    'url' => $url,
                    'out_trade_no' => $out_trade_no,               //微信交易单号
                ];
            } else {
                $this->error('参数错误');
            }
            return view();
        }
    } else {
        $user = cmf_get_current_user();
        $this->assign($user);
        return $this->fetch();
    }
}

//轮询订单
public function payFind()
{
    //商家订单号
    $out_trade_no = $this->request->param('out_trade_no');

    $status = DB::name('recharge')
        ->where('out_trade_no', $out_trade_no) //商户自定义订单号
        ->value('status');

    if ($status == 2) {
        $this->success("支付成功");
    } else {
        $this->error('支付失败');
    }
}

回调操作(回调url一定要写可访问的url 避免权限问题)

<?php
namespace app\common\controller;

use cmf\controller\BaseController;
use think\Db;

//第三方接口
class ThirdController extends BaseController
{

    /**
     * wx支付回调处理
     */
    //$xmlObj 输出内容
    // Array
    // (
    //     [appid] => XXXX
    //     [attach] => 扫码支付0.01元
    //     [bank_type] => OTHERS
    //     [cash_fee] => 1
    //     [fee_type] => CNY
    //     [is_subscribe] => Y
    //     [mch_id] => 1574582441
    //     [nonce_str] => XXXX
    //     [openid] => XXXX
    //     [out_trade_no] => XXXX
    //     [result_code] => SUCCESS
    //     [return_code] => SUCCESS
    //     [sign] => XXXXX
    //     [time_end] => 20200124125552
    //     [total_fee] => 1
    //     [trade_type] => NATIVE
    //     [transaction_id] => XXXX
    // )
    public function paycallback()
    {
        //获取微信回调的数据
        $notifiedData = file_get_contents('php://input');
        // cmh_log('pay',$notifiedData);
        //XML格式转换
        $xmlObj = simplexml_load_string($notifiedData, 'SimpleXMLElement', LIBXML_NOCDATA);
        $xmlObj = json_decode(json_encode($xmlObj), true);

        $this->cmh_log('pay', print_r($xmlObj, true));

        //支付成功
        if ($xmlObj['return_code'] == "SUCCESS" && $xmlObj['result_code'] == "SUCCESS") {
            foreach ($xmlObj as $k => $v) {
                if ($k == 'sign') {
                    $xmlSign = $xmlObj[$k];
                    unset($xmlObj[$k]);
                };
            }
            $sign = $this->WxSign($xmlObj);
            if ($sign === $xmlSign) {

                //改变订单状态
                DB::name('recharge')
                    ->where('out_trade_no', $xmlObj['out_trade_no']) //商户自定义订单号
                    ->update([
                        'transaction_id' => $xmlObj['transaction_id'],   //微信交易单号
                        'status'         => 2,                           //已支付
                        'end_time'       => time()                       //完成时间
                    ]);

                $recharge = DB::name('recharge')
                    ->where('out_trade_no', $xmlObj['out_trade_no']) //商户自定义订单号
                    ->field('uid,total_fee')
                    ->find();

                //增加用户余额
                DB::name('user')
                    ->where('id', $recharge['uid'])
                    ->setInc('balance', $recharge['total_fee']);

                //告诉微信已经收到了
                return sprintf("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");;
            }
        }
    }

    //微信签名算法
    private function WxSign($param)
    {
        $signkey = 'XXXX'; //秘钥
        $sign = '';
        foreach ($param as $key => $val) {
            $sign .= $key . '=' . $val . '&';
        }
        $sign .= 'key=' . $signkey;
        $sign = strtoupper(MD5($sign));
        return $sign;
    }
	/**
	 * 统一日志记录
	 * @author  
	 * @date    
	 * @param   string  $path  路径
	 * @param   string  $content  日志内容
	 * @param   string  $mode  记录格式,day=天,month=月,year=年
	 * @param   string  $env  请求模式
	 *
	 * @return  bool
	 */
	function cmh_log($path, $content, $mode = 'day', $env = '')
	{
	    if (!$content) {
	        return false;
	    }
	    $content = strval($content) . "\n";
	    if (PHP_SAPI == 'cli') {
	        $path = 'cli/' . $path;
	    }
	    $path = '/www/wwwroot/log/' . $path . '/';
	    if ($mode == 'year') {
	        $fileName = date('Y') . '.log';
	    } else if ($mode == 'month') {
	        $path = $path . date('Y');
	        $fileName = '/' . date('m') . '.log';
	    } else {
	        $path = $path . date('Y') . '/' . date('m') . '/';
	        $fileName =  date('d') . '.log';
	    }
	    if (!is_dir($path)) {
	        $res = mkdir($path, 0777, true);
	        if (!$res) {
	            return false;
	        }
	    }
	    $file = $path . $fileName;
	    $content = date('Y-m-d H:i:s') . ':' . $content;
	    $res = file_put_contents($file, $content, FILE_APPEND);
	    if ($res) {
	        return true;
	    } else {
	        return false;
	    }
	}
}



发布了65 篇原创文章 · 获赞 20 · 访问量 2100

猜你喜欢

转载自blog.csdn.net/weixin_43993175/article/details/104036664