PHP-Tp5-微信扫码支付

微信扫码支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3

官方demo下载:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

官方下载demo,目录结构如下:

引入微信支付

把 lib 文件夹复制到你需要添加的扩展文件夹下,重命名为wxpay,我在这里放到extend目录下

把 example 文件夹下的 WxPay.Config.php 拿出来,放到wxpay目录下,修改require_once,并配置支付参数:

<?php
/**
*
* example目录下为简单的支付样例,仅能用于搭建快速体验微信支付使用
* 样例的作用仅限于指导如何使用sdk,在安全上面仅做了简单处理, 复制使用样例代码时请慎重
* 请勿直接直接使用样例对外提供服务
* 
**/
require_once "WxPay.Config.Interface.php";

/**
*
* 该类需要业务自己继承, 该类只是作为deamon使用
* 实际部署时,请务必保管自己的商户密钥,证书等
* 
*/

class WxPayConfig extends WxPayConfigInterface
{
	//=======【基本信息设置】=====================================
	/**
	 * TODO: 修改这里配置为您自己申请的商户信息
	 * 微信公众号信息配置
	 * 
	 * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)wx75502ffcfac1522e
	 * 
	 * MCHID:商户号(必须配置,开户邮件中可查看)1516924601
	 * 
	 */
	public function GetAppId()
	{
		return 'xxx';
	}
	public function GetMerchantId()
	{
		return 'xxx';
	}
	
	//=======【支付相关配置:支付成功回调地址/签名方式】===================================
	/**
	* TODO:支付回调url
	* 签名和验证签名方式, 支持md5和sha256方式
	**/
	public function GetNotifyUrl()
	{
		return "xxx";
	}
	public function GetSignType()
	{
		return "HMAC-SHA256";
	}

	//=======【curl代理设置】===================================
	/**
	 * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
	 * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
	 * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
	 * @var unknown_type
	 */
	public function GetProxy(&$proxyHost, &$proxyPort)
	{
		$proxyHost = "0.0.0.0";
		$proxyPort = 0;
	}
	

	//=======【上报信息配置】===================================
	/**
	 * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
	 * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
	 * 开启错误上报。
	 * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
	 * @var int
	 */
	public function GetReportLevenl()
	{
		return 1;
	}


	//=======【商户密钥信息-需要业务方继承】===================================
	/*
	 * 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 'xxx';
	}
	public function GetAppSecret()
	{
		return '';
	}


	//=======【证书路径设置-需要业务方继承】=====================================
	/**
	 * TODO:设置商户证书路径
	 * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
	 * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
	 * 注意:
	 * 1.证书文件不能放在web服务器虚拟目录,应放在有访问权限控制的目录中,防止被他人下载;
	 * 2.建议将证书文件名改为复杂且不容易猜测的文件名;
	 * 3.商户服务器要做好病毒和木马防护工作,不被非法侵入者窃取证书文件。
	 * @var path
	 */
	public function GetSSLCertPath(&$sslCertPath, &$sslKeyPath)
	{
		$sslCertPath = 'cert/apiclient_cert.pem';
		$sslKeyPath = 'cert/apiclient_key.pem';
	}
}

修改 WxPay.Api.php 第二个require_once:

require_once "WxPay.Config.php";


统一下单:


官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

接口链接:

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

URL地址:https://api2.mch.weixin.qq.com/pay/unifiedorder(备用域名)见跨城冗灾方案

是否需要证书:

 请求参数:

字段名变量名必填类型示例值描述
公众账号IDappidString(32)wxd678efh567hg6787微信支付分配的公众账号ID(企业号corpid即为此appId)
商户号mch_idString(32)1230000109微信支付分配的商户号
设备号device_infoString(32)013467007045764自定义参数,可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB"
随机字符串nonce_strString(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,长度要求在32位以内。推荐随机数生成算法
签名signString(32)C380BEC2BFD727A4B6845133519F3AD6通过签名算法计算得出的签名值,详见签名生成算法
签名类型sign_typeString(32)MD5签名类型,默认为MD5,支持HMAC-SHA256和MD5。
商品描述bodyString(128)腾讯充值中心-QQ会员充值

商品简单描述,该字段请按照规范传递,具体请见参数规定

商品详情detailString(6000) 商品详细描述,对于使用单品优惠的商户,该字段必须按照规范上传,详见“单品优惠参数说明”
附加数据attachString(127)深圳分店附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
商户订单号out_trade_noString(32)20150806125346商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一。详见商户订单号
标价币种fee_typeString(16)CNY符合ISO 4217标准的三位字母代码,默认人民币:CNY,详细列表请参见货币类型
标价金额total_feeInt88订单总金额,单位为分,详见支付金额
终端IPspbill_create_ipString(64)123.12.12.123支持IPV4和IPV6两种格式的IP地址。用户的客户端IP
交易起始时间time_startString(14)20091225091010订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
交易结束时间time_expireString(14)20091227091010

订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。订单失效时间是针对订单号而言的,由于在请求支付的时候有一个必传参数prepay_id只有两小时的有效期,所以在重入时间超过2小时的时候需要重新请求下单接口获取新的prepay_id。其他详见时间规则

time_expire只能第一次下单传值,不允许二次修改,二次修改系统将报错。如用户支付失败后,需再次支付,需更换原订单号重新下单。

建议:最短失效时间间隔大于1分钟

订单优惠标记goods_tagString(32)WXG订单优惠标记,使用代金券或立减优惠功能时需要的参数,说明详见代金券或立减优惠
通知地址notify_urlString(256)http://www.weixin.qq.com/wxpay/pay.php异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
交易类型trade_typeString(16)JSAPI

JSAPI -JSAPI支付

NATIVE -Native支付

APP -APP支付

说明详见参数规定

商品IDproduct_idString(32)12235413214070356458058trade_type=NATIVE时,此参数必传。此参数为二维码中包含的商品ID,商户自行定义。
指定支付方式limit_payString(32)no_credit上传此参数no_credit--可限制用户不能使用信用卡支付
用户标识openidString(128)oUpF8uMuAJO_M2pxb1Q9zNjWeS6otrade_type=JSAPI时(即JSAPI支付),此参数必传,此参数为微信用户在商户对应appid下的唯一标识。openid如何获取,可参考【获取openid】。企业号请使用【企业号OAuth2.0接口】获取企业号内成员userid,再调用【企业号userid转openid接口】进行转换
电子发票入口开放标识receiptString(8)YY,传入Y时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效
+场景信息scene_infoString(256)

{"store_info" : {
"id": "SZTX001",
"name": "腾大餐厅",
"area_code": "440305",
"address": "科技园中一路腾讯大厦" }}

该字段常用于线下活动时的场景信息上报,支持上报实际门店信息,商户也可以按需求自己上报相关信息。该字段为JSON对象数据,对象格式为{"store_info":{"id": "门店ID","name": "名称","area_code": "编码","address": "地址" }} ,字段详细说明请点击行前的+展开

下单


WechatPay.php控制器:

public function pay($payMoney, $orderSn, $goodId)
    {
        require ROOT_PATH . 'extend' . DS . 'wxpay/WxPay.Api.php'; //引入微信支付
        $input = new \WxPayUnifiedOrder();//统一下单
        $config = new \WxPayConfig();//配置参数

        $goods_name = '扫码支付' . $payMoney . '元'; //商品名称(自定义)
        // 商品描述
        $input->SetBody($goods_name);
        // 附加数据
//        $input->SetAttach($goods_name);
        // 商户订单号
        $input->SetOut_trade_no($orderSn);
        // 标价金额 (订单总金额,单位为分)
        $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($this->notifyUrl); //回调地址
        // 交易类型
        $input->SetTrade_type("NATIVE");
        // 商品ID
        $input->SetProduct_id($goodId);

        $result = \WxPayApi::unifiedOrder($config, $input);
        if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
            // 请求成功,返回url
            $url = $result["code_url"];
            return ['code' => 1, 'url' => $url];
        } else {
            return ['code' => 0, 'msg' => $result['err_code_des']];
        }
    }

生成支付二维码:

这里使用QRCode.js生成二维码,首先下载QRCode.js,下载地址:https://github.com/davidshimjs/qrcodejs

html:

<div class="layui-card-body">
    <div class="content" style="border:1px solid #ccc;width: 170px;height: 160px; margin: 0 auto;padding: 10px;">
        <input type="hidden" id="url" value="{$data.url}">
        <div id="qrcode" style="width: 150px;height: 150px;margin: 0 auto;"></div>
    </div>

    <p style="text-align: center">使用微信扫一扫付款</p>
</div>

js:

// 获取支付链接
var url = $("#url").val();
var qrcode = new QRCode(document.getElementById("qrcode"), { // 显示二维码的元素或该元素的 ID
    text: url,   // 支付链接
    width: 150,          //设置宽度
    height: 150,        // 设置高度
    colorDark : "#000000",        // 设置前景色
    colorLight : "#ffffff",        // 设置背景色
    correctLevel : QRCode.CorrectLevel.L       // 设置容错级别
});

二维码:

支付页面查询订单:

$(function(){
    setInterval(function(){check()}, 3000);  //3秒查询一次支付是否成功
});
function check(){
    var url = "{:url('orderquery','',false)}";
    var param = {'outTradeNo':outTradeNo}; // 订单号
    $.post(url, param, function(data){
        if(data['code'] == 0){
            layer.msg("订单支付成功,即将跳转...");
            // 支付成功之后的操作
        }
    });
}

PHP: 

// 查询订单
public function orderquery($outTradeNo)
{
    $config = array(
        'mch_id' => $this->mchid,
        'appid' => $this->appid,
        'key' => $this->apiKey,
    );
    //$orderName = iconv('GBK','UTF-8',$orderName);
    $unified = array(
        'appid' => $config['appid'],
        'mch_id' => $config['mch_id'],
        'out_trade_no' => $outTradeNo,
        'nonce_str' => self::createNonceStr(),
    );
    $unified['sign'] = self::getSign($unified, $config['key']);
    $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/orderquery', self::arrayToXml($unified));
    $queryResult = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
    if ($queryResult === false) {
        die('parse xml error');
    }
    if ($queryResult->return_code != 'SUCCESS') {
        die($queryResult->return_msg);
    }
    $trade_state = $queryResult->trade_state;
    $data['code'] = $trade_state=='SUCCESS' ? 0 : 1;
    $data['data'] = $trade_state;
    $data['msg'] = $this->getTradeSTate($trade_state);
    $data['time'] = date('Y-m-d H:i:s');
    return $data;
}

public function getTradeSTate($str)
{
    switch ($str){
        case 'SUCCESS';
            return '支付成功';
        case 'REFUND';
            return '转入退款';
        case 'NOTPAY';
            return '未支付';
        case 'CLOSED';
            return '已关闭';
        case 'REVOKED';
            return '已撤销(刷卡支付)';
        case 'USERPAYING';
            return '用户支付中';
        case 'PAYERROR';
            return '支付失败';
    }
}

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

/**
 * 获取签名
 */
public static function getSign($params, $key)
{
    ksort($params, SORT_STRING);
    $unSignParaString = self::formatQueryParaMap($params, false);
    $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
    return $signStr;
}

protected static function formatQueryParaMap($paraMap, $urlEncode = false)
{
    $buff = "";
    ksort($paraMap);
    foreach ($paraMap as $k => $v) {
        if (null != $v && "null" != $v) {
            if ($urlEncode) {
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }
    }
    $reqPar = '';
    if (strlen($buff) > 0) {
        $reqPar = substr($buff, 0, strlen($buff) - 1);
    }
    return $reqPar;
}

public static function arrayToXml($arr)
{
    $xml = "<xml>";
    foreach ($arr as $key => $val) {
        if (is_numeric($val)) {
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
        } else
            $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
    }
    $xml .= "</xml>";
    return $xml;
}

public static function curlPost($url = '', $postData = '', $options = array())
{
    if (is_array($postData)) {
        $postData = http_build_query($postData);
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
    if (!empty($options)) {
        curl_setopt_array($ch, $options);
    }
    //https请求 不验证证书和host
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $data = curl_exec($ch);
    curl_close($ch);
    return $data;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值