• 技术文章 >后端开发 >php教程

    随着微信支付的升级,PHP微信支付类V3接口也来了

    藏色散人藏色散人2021-07-15 14:27:54转载740

    不知不觉微信支付也更新了,接口版本也升级到了V3,跟着微信的升级,将个人使用微信支付类也进行了升级,V3微信支付文档:https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml。

    使用方法还和之前的一样(V2微信支付),直接传递参数就可使用:

    新版新增了composer安装,便于集成框架使用(Github地址):

    composer require fengkui/pay

    首先把配置文件填写完整(细心不要填错,否则会导致签名错误):

    # 微信支付配置
    $wechatConfig = [
        'xcxid'         => '', // 小程序 appid
        'appid'         => '', // 微信支付 appid
        'mchid'         => '', // 微信支付 mch_id 商户收款账号
        'key'           => '', // 微信支付 apiV3key(尽量包含大小写字母,否则验签不通过)
        'appsecret'     => '', // 公众帐号 secert (公众号支付获取 code 和 openid 使用)
    
        'notify_url'    => '', // 接收支付状态的连接  改成自己的回调地址
        'redirect_url'  => '', // 公众号支付,调起支付页面
    
        'serial_no'     => '', // 证书序列号
        'cert_client'   => './cert/apiclient_cert.pem', // 证书(退款,红包时使用)
        'cert_key'      => './cert/apiclient_key.pem', // 商户私钥(Api安全中下载)
        'public_key'    => './cert/public_key.pem', // 平台公钥(调动证书列表,自动生成)
    ];

    支付类封装相关方法:

    method描述
    jsJSAPI下单
    appAPP支付
    h5H5支付
    scanNavicat支付
    xcx小程序支付
    query查询订单
    close关闭订单
    refund申请退款
    notify支付结果通知

    使用方法(这里已小程序支付为示例):

    <?php
    require_once('./vendor/autoload.php');
    
    $config = []; // 支付配置
    $order = [
        'order_sn' => time(), // 订单编号
        'total_amount' => 1, // 订单金额(分)
        'body' => '测试商品', // 商品名称
        'openid' => '', // 用户openid
        // 'type' => 'Wap',
    ];
    
    $wechat = new fengkui\Pay\Wechat($config);
    $re = $wechat->xcx($order);
    die(json_encode($re)); // JSON化直接返回小程序客户端

    如下代码是封装好的完整支付类文件(Wechat.php),
    可以根据自己需求随意修改,详细的使用方法后期会有文档:

    <?php
    /**
     * @Author: [FENG] <1161634940@qq.com>
     * @Date:   2019-09-06 09:50:30
     * @Last Modified by:   [FENG] <1161634940@qq.com>
     * @Last Modified time: 2021-07-12 18:24:18
     */
    namespace fengkui\Pay;
    
    use Exception;
    use RuntimeException;
    use fengkui\Supports\Http;
    
    /**
     * Wechat 微信支付
     * 新版(V3)接口(更新中)
     */
    class Wechat
    {
        const AUTH_TAG_LENGTH_BYTE = 16;
    
        // 新版相关接口
        // GET 获取平台证书列表
        private static $certificatesUrl = 'https://api.mch.weixin.qq.com/v3/certificates';
        // 统一下订单管理
        private static $transactionsUrl = 'https://api.mch.weixin.qq.com/v3/pay/transactions/';
        // 申请退款
        private static $refundUrl = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
        // 静默授权,获取code
        private static $authorizeUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize';
        // 通过code获取access_token以及openid
        private static $accessTokenUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token';
    
        // 支付完整配置
        private static $config = array(
            'xcxid'         => '', // 小程序appid
            'appid'         => '', // 微信支付appid
            'mchid'         => '', // 微信支付 mch_id 商户收款账号
            'key'           => '', // 微信支付 apiV3key(尽量包含大小写字母,否则验签不通过)
            'appsecret'     => '', // 公众帐号 secert (公众号支付获取code 和 openid使用)
    
            'notify_url'    => '', // 接收支付状态的连接  改成自己的回调地址
            'redirect_url'  => '', // 公众号支付,调起支付页面
    
            'serial_no'     => '', // 证书序列号
            'cert_client'   => './cert/apiclient_cert.pem', // 证书(退款,红包时使用)
            'cert_key'      => './cert/apiclient_key.pem', // 商户私钥(Api安全中下载)
            'public_key'    => './cert/public_key.pem', // 平台公钥(调动证书列表,自动生成)
        );
    
        /**
         * [__construct 构造函数]
         * @param [type] $config [传递微信支付相关配置]
         */
        public function __construct($config=NULL, $referer=NULL){
            $config && self::$config = array_merge(self::$config, $config);
        }
    
        /**
         * [unifiedOrder 统一下单]
         * @param  [type]  $order [订单信息(必须包含支付所需要的参数)]
         * @param  boolean $type  [区分是否是小程序,是则传 true]
         * @return [type]         [description]
         * $order = array(
         *      'body'         => '', // 产品描述
         *      'order_sn'     => '', // 订单编号
         *      'total_amount' => '', // 订单金额(分)
         * );
         */
        public static function unifiedOrder($order, $type=false)
        {
            $config = array_filter(self::$config);
    
            // 获取配置项
            $params = array(
                'appid'         => $type ? $config['xcxid'] : $config['appid'], // 由微信生成的应用ID
                'mchid'         => $config['mchid'], // 直连商户的商户号
                'description'   => $order['body'], // 商品描述
                'out_trade_no'  => (string)$order['order_sn'], // 商户系统内部订单号
                'notify_url'    => $config['notify_url'], // 通知URL必须为直接可访问的URL
                'amount'        => ['total' => (int)$order['total_amount'], 'currency' => 'CNY'], // 订单金额信息
            );
    
            !empty($order['attach']) && $params['attach'] = $order['attach']; // 附加数据
            if (!empty($order['time_expire'])) { // 订单失效时间
                preg_match('/[年\/-]/', $order['time_expire']) && $order['time_expire'] = strtotime($order['time_expire']);
                $time = $order['time_expire'] > time() ? $order['time_expire'] : $order['time_expire'] + time();
                $params['time_expire'] = date(DATE_ATOM, $time);
            }
    
            if (!in_array($order['type'], ['native'])) {
                !empty($order['openid']) && $params['payer'] = ['openid' => $order['openid']];
                $params['scene_info'] = ['payer_client_ip' => self::get_ip()];
            }
    
            if (in_array($order['type'], ['iOS', 'Android', 'Wap'])) {
                $params['scene_info']['h5_info'] = ['type' => $order['type']];
                $url = self::$transactionsUrl . 'h5'; // 拼接请求地址
            } else {
                $url = self::$transactionsUrl . strtolower($order['type']); // 拼接请求地址
            }
    
            $header = self::createAuthorization($url, $params, 'POST');
            $response = Http::post($url, json_encode($params, JSON_UNESCAPED_UNICODE), $header);
            $result = json_decode($response, true);
            if (isset($result['code']) && isset($result['message'])) {
                throw new \Exception("[" . $result['code'] . "] " . $result['message']);
            }
    
            return $result;
        }
    
        /**
         * [query 查询订单]
         * @param  [type]  $orderSn [订单编号]
         * @param  boolean $type    [微信支付订单编号,是否是微信支付订单号]
         * @return [type]           [description]
         */
        public static function query($orderSn, $type = false)
        {
            $config = self::$config;
            $url = self::$transactionsUrl . ($type ? 'id/' : 'out-trade-no/') . $orderSn . '?mchid=' . $config['mchid'];
            $params = '';
    
            $header = self::createAuthorization($url, $params, 'GET');
            $response = Http::get($url, $params, $header);
            $result = json_decode($response, true);
    
            return $result;
        }
    
        /**
         * [close 关闭订单]
         * @param  [type] $orderSn [微信支付订单编号]
         * @return [type]          [description]
         */
        public static function close($orderSn)
        {
            $config = self::$config;
            $url = self::$transactionsUrl . 'out-trade-no/' . $orderSn . '/close';
            $params['mchid'] = $config['mchid'];
    
            $header = self::createAuthorization($url, $params, 'POST');
            $response = Http::post($url, json_encode($params, JSON_UNESCAPED_UNICODE), $header);
            $result = json_decode($response, true);
    
            return true;
        }
    
        /**
         * [js 获取jssdk需要用到的数据]
         * @param  [type] $order [订单信息数组]
         * @return [type]        [description]
         */
        public static function js($order=[]){
            $config = self::$config;
            if (!is_array($order) || count($order) < 3)
                die("订单数组信息缺失!");
            if (count($order) == 4 && !empty($order['openid'])) {
                $data = self::xcx($order, false, false); // 获取支付相关信息(获取非小程序信息)
                return $data;
            }
            $code = !empty($order['code']) ? $order['code'] : ($_GET['code'] ?? '');
            $redirectUri = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . rtrim($_SERVER['REQUEST_URI'], '/') . '/'; // 重定向地址
    
            $params = ['appid' => $config['appid']];
            // 如果没有get参数没有code;则重定向去获取code;
            if (empty($code)) {
                $params['redirect_uri'] = $redirectUri; // 返回的url
                $params['response_type'] = 'code';
                $params['scope'] = 'snsapi_base';
                $params['state'] = $order['order_sn']; // 获取订单号
    
                $url = self::$authorizeUrl . '?'. http_build_query($params) .'#wechat_redirect';
            } else {
                $params['secret'] = $config['appsecret'];
                $params['code'] = $code;
                $params['grant_type'] = 'authorization_code';
    
                $response = Http::get(self::$accessTokenUrl, $params); // 进行GET请求
                $result = json_decode($response, true);
    
                $order['openid'] = $result['openid']; // 获取到的openid
                $data = self::xcx($order, false, false); // 获取支付相关信息(获取非小程序信息)
    
                if (!empty($order['code'])) {
                    return $data;
                }
    
                $url = $config['redirect_url'] ?? $redirectUri;
                $url .= '?data=' . json_encode($data, JSON_UNESCAPED_UNICODE);
            }
            header('Location: '. $url);
            die;
        }
    
        /**
         * [app 获取APP支付需要用到的数据]
         * @param  [type]  $order [订单信息数组]
         * @return [type]         [description]
         */
        public static function app($order=[], $log=false)
        {
            if(empty($order['order_sn']) || empty($order['total_amount']) || empty($order['body'])){
                die("订单数组信息缺失!");
            }
    
            $order['type'] = 'app'; // 获取订单类型,用户拼接请求地址
            $result = self::unifiedOrder($order, true);
            if (!empty($result['prepay_id'])) {
                $data = array (
                    'appId'     => self::$config['appid'], // 微信开放平台审核通过的移动应用appid
                    'timeStamp' => (string)time(),
                    'nonceStr'  => self::get_rand_str(32, 0, 1), // 随机32位字符串
                    'prepayid'  => $result['prepay_id'],
                );
                $data['paySign'] = self::makeSign($data);
                $data['partnerid'] = $config['mchid'];
                $data['package'] = 'Sign=WXPay';
                return $data; // 数据小程序客户端
            } else {
                return $log ? $result : false;
            }
        }
    
        /**
         * [h5 微信H5支付]
         * @param  [type] $order [订单信息数组]
         * @return [type]        [description]
         */
        public static function h5($order=[], $log=false)
        {
            if(empty($order['order_sn']) || empty($order['total_amount']) || empty($order['body']) || empty($order['type']) || !in_array(strtolower($order['type']), ['ios', 'android', 'wap'])){
                die("订单数组信息缺失!");
            }
            $result = self::unifiedOrder($order);
            if (!empty($result['h5_url'])) {
                return $result['h5_url']; // 返回链接让用户点击跳转
            } else {
                return $log ? $result : false;
            }
        }
    
        /**
         * [xcx 获取jssdk需要用到的数据]
         * @param  [type]  $order [订单信息数组]
         * @param  boolean $log   [description]
         * @param  boolean $type  [区分是否是小程序,默认 true]
         * @return [type]         [description]
         */
        public static function xcx($order=[], $log=false, $type=true)
        {
            if(empty($order['order_sn']) || empty($order['total_amount']) || empty($order['body']) || empty($order['openid'])){
                die("订单数组信息缺失!");
            }
    
            $order['type'] = 'jsapi'; // 获取订单类型,用户拼接请求地址
            $config = self::$config;
            $result = self::unifiedOrder($order, $type);
            if (!empty($result['prepay_id'])) {
                $data = array (
                    'appId'     => $type ? $config['xcxid'] : $config['appid'], // 由微信生成的应用ID
                    'timeStamp' => (string)time(),
                    'nonceStr'  => self::get_rand_str(32, 0, 1), // 随机32位字符串
                    'package'   => 'prepay_id='.$result['prepay_id'],
                );
                $data['paySign'] = self::makeSign($data);
                $data['signType'] = 'RSA';
                return $data; // 数据小程序客户端
            } else {
                return $log ? $result : false;
            }
        }
    
        /**
         * [scan 微信扫码支付]
         * @param  [type] $order [订单信息数组]
         * @return [type]        [description]
         */
        public static function scan($order=[], $log=false)
        {
            if(empty($order['order_sn']) || empty($order['total_amount']) || empty($order['body'])){
                die("订单数组信息缺失!");
            }
            $order['type'] = 'native'; // Native支付
            $result = self::unifiedOrder($order);
    
            if (!empty($result['code_url'])) {
                return urldecode($result['code_url']); // 返回链接让用户点击跳转
            } else {
                return $log ? $result : false;
            }
        }
    
        /**
         * [notify 回调验证]
         * @return [array] [返回数组格式的notify数据]
         */
        public static function notify($server = [], $response = [])
        {
            $config = self::$config;
            $server = $server ?? $_SERVER;
            $response = $response ?? file_get_contents('php://input', 'r');
            if (empty($response) || empty($server['HTTP_WECHATPAY_SIGNATURE'])) {
                return false;
            }
            $body = [
                'timestamp' => $server['HTTP_WECHATPAY_TIMESTAMP'],
                'nonce' => $server['HTTP_WECHATPAY_NONCE'],
                'data' => $response,
            ];
            // 验证应答签名
            $verifySign = self::verifySign($body, trim($server['HTTP_WECHATPAY_SIGNATURE']), trim($server['HTTP_WECHATPAY_SERIAL']));
            if (!$verifySign) {
                die("签名验证失败!");
            }
            $result = json_decode($response, true);
            if (empty($result) || $result['event_type'] != 'TRANSACTION.SUCCESS' || $result['summary'] != '支付成功') {
                return false;
            }
            // 加密信息
            $associatedData = $result['resource']['associated_data'];
            $nonceStr = $result['resource']['nonce'];
            $ciphertext = $result['resource']['ciphertext'];
            $data = $result['resource']['ciphertext'] = self::decryptToString($associatedData, $nonceStr, $ciphertext);
    
            return json_decode($data, true);
        }
    
        /**
         * [refund 微信支付退款]
         * @param  [type] $order [订单信息]
         * @param  [type] $type  [是否是小程序]
         */
        public static function refund($order)
        {
            $config = self::$config;
            if(empty($order['refund_sn']) || empty($order['refund_amount']) || (empty($order['order_sn']) && empty($order['transaction_id']))){
                die("订单数组信息缺失!");
            }
    
            $params = array(
                'out_refund_no' => (string)$order['refund_sn'], // 商户退款单号
                'funds_account' => 'AVAILABLE', // 退款资金来源
                'amount' => [
                        'refund' => $order['refund_amount'],
                        'currency' => 'CNY',
                    ]
            );
    
            if (!empty($order['transaction_id'])) {
                $params['transaction_id'] = $order['transaction_id'];
                $orderDetail = self::query($order['transaction_id'], true);
            } else {
                $params['out_trade_no'] = $order['order_sn'];
                $orderDetail = self::query($order['order_sn']);
            }
            $params['amount']['total'] = $orderDetail['amount']['total'];
            !empty($order['reason']) && $params['reason'] = $order['reason'];
    
            $url = self::$refundUrl;
            $header = self::createAuthorization($url, $params, 'POST');
            $response = Http::post($url, json_encode($params, JSON_UNESCAPED_UNICODE), $header);
            $result = json_decode($response, true);
    
            return $result;
        }
    
        /**
         * [queryRefund 查询退款]
         * @param  [type] $refundSn [退款单号]
         * @return [type]           [description]
         */
        public static function queryRefund($refundSn, $type = false)
        {
            $url = self::$refundUrl . '/' . $refundSn;
            $params = '';
    
            $header = self::createAuthorization($url, $params, 'GET');
            $response = Http::get($url, $params, $header);
            $result = json_decode($response, true);
    
            return $result;
        }
    
        /**
         * [success 通知支付状态]
         */
        public static function success()
        {
            $str = ['code'=>'SUCCESS', 'message'=>'成功'];
            die(json_encode($str, JSON_UNESCAPED_UNICODE));
        }
    
        /**
         * [createAuthorization 获取接口授权header头信息]
         * @param  [type] $url    [请求地址]
         * @param  array  $data   [请求参数]
         * @param  string $method [请求方式]
         * @return [type]         [description]
         */
        //生成v3 Authorization
        protected static function createAuthorization($url, $data=[], $method='POST'){
            $config = self::$config;
            //商户号
            $mchid = $config['mchid'];
            // 证书序列号
            if (empty($config['serial_no'])) {
                $certFile = @file_get_contents($config['cert_client']);
                $certArr = openssl_x509_parse($publicStr);
                $serial_no = $certArr['serialNumberHex'];
            } else {
                $serial_no = $config['serial_no'];
            }
    
            // 解析url地址
            $url_parts = parse_url($url);
            //生成签名
            $body = [
                'method' => $method,
                'url'   => ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : "")),
                'time'  => time(), // 当前时间戳
                'nonce' => self::get_rand_str(32, 0, 1), // 随机32位字符串
                'data'  => (strtolower($method) == 'post' ? json_encode($data, JSON_UNESCAPED_UNICODE) : $data), // POST请求时 需要 转JSON字符串
            ];
            $sign = self::makeSign($body);
            //Authorization 类型
            $schema = 'WECHATPAY2-SHA256-RSA2048';
            //生成token
            $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $body['nonce'], $body['time'], $serial_no, $sign);
    
            $header = [
                'Content-Type:application/json',
                'Accept:application/json',
                'User-Agent:*/*',
                'Authorization: '.  $schema . ' ' . $token
            ];
            return $header;
        }
    
        /**
         * [makeSign 生成签名]
         * @param  [type] $data [加密数据]
         * @return [type]       [description]
         */
        public static function makeSign($data)
        {
            $config = self::$config;
            if (!in_array('sha256WithRSAEncryption', \openssl_get_md_methods(true))) {
                throw new \RuntimeException("当前PHP环境不支持SHA256withRSA");
            }
            // 拼接生成签名所需的字符串
            $message = '';
            foreach ($data as $value) {
                $message .= $value . "\n";
            }
            // 商户私钥
            $private_key = self::getPrivateKey($config['cert_key']);
            // 生成签名
            openssl_sign($message, $sign, $private_key, 'sha256WithRSAEncryption');
            $sign = base64_encode($sign);
            return $sign;
        }
    
        /**
         * [verifySign 验证签名]
         * @param  [type] $data   [description]
         * @param  [type] $sign   [description]
         * @param  [type] $serial [description]
         * @return [type]         [description]
         */
        public static function verifySign($data, $sign, $serial)
        {
            $config = self::$config;
            if (!in_array('sha256WithRSAEncryption', \openssl_get_md_methods(true))) {
                throw new \RuntimeException("当前PHP环境不支持SHA256withRSA");
            }
            $sign = \base64_decode($sign);
            // 拼接生成签名所需的字符串
            $message = '';
            foreach ($data as $value) {
                $message .= $value . "\n";
            }
            // 获取证书相关信息
            self::certificates($serial);
            // 平台公钥
            $public_key = self::getPublicKey($config['public_key']); //平台公钥
            // 验证签名
            $recode = \openssl_verify($message, $sign, $public_key, 'sha256WithRSAEncryption');
            return $recode == 1 ? true : false;
        }
    
        //获取私钥
        public static function getPrivateKey($filepath)
        {
            return openssl_pkey_get_private(file_get_contents($filepath));
        }
    
        //获取公钥
        public static function getPublicKey($filepath)
        {
            return openssl_pkey_get_public(file_get_contents($filepath));
        }
    
        /**
         * [certificates 获取证书]
         * @return [type] [description]
         */
        public static function certificates($serial)
        {
            $config = self::$config;
    
            $publicStr = @file_get_contents($config['public_key']);
            if ($publicStr) { // 判断证书是否存在
                $openssl = openssl_x509_parse($publicStr);
                if ($openssl['serialNumberHex'] == $serial) { // 是否是所需证书
                    // return self::getPublicKey($config['public_key']); //平台公钥
                    return '';
                }
            }
    
            $url = self::$certificatesUrl;
            $params = '';
    
            $header = self::createAuthorization($url, $params, 'GET');
            $response = Http::get($url, $params, $header);
            $result = json_decode($response, true);
            if (empty($result['data'])) {
                throw new RuntimeException("[" . $result['code'] . "] " . $result['message']);
            }
            foreach ($result['data'] as $key => $certificate) {
                if ($certificate['serial_no'] == $serial) {
                    $publicKey = self::decryptToString(
                        $certificate['encrypt_certificate']['associated_data'],
                        $certificate['encrypt_certificate']['nonce'],
                        $certificate['encrypt_certificate']['ciphertext']
                    );
                    file_put_contents($config['public_key'], $publicKey);
                    break; // 终止循环
                }
                // self::$publicKey[$certificate['serial_no']] = $publicKey;
            }
            // return self::getPublicKey($config['public_key']); //平台公钥
        }
    
        /**
         * [decryptToString 证书和回调报文解密]
         * @param  [type] $associatedData [附加数据包(可能为空)]
         * @param  [type] $nonceStr       [加密使用的随机串初始化向量]
         * @param  [type] $ciphertext     [Base64编码后的密文]
         * @return [type]                 [description]
         */
        public static function decryptToString($associatedData, $nonceStr, $ciphertext)
        {
            $config = self::$config;
            $ciphertext = base64_decode($ciphertext);
            if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
                return false;
            }
    
            // ext-sodium (default installed on >= PHP 7.2)
            if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
                \sodium_crypto_aead_aes256gcm_is_available()) {
                return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $config['key']);
            }
    
            // ext-libsodium (need install libsodium-php 1.x via pecl)
            if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
                \Sodium\crypto_aead_aes256gcm_is_available()) {
                return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $config['key']);
            }
    
            // openssl (PHP >= 7.1 support AEAD)
            if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
                $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
                $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
    
                return \openssl_decrypt($ctext, 'aes-256-gcm', $config['key'], \OPENSSL_RAW_DATA, $nonceStr,
                    $authTag, $associatedData);
            }
    
            throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
        }
    
        /** fengkui.net
         * [get_rand_str 获取随机字符串]
         * @param  integer $randLength    [长度]
         * @param  integer $addtime       [是否加入当前时间戳]
         * @param  integer $includenumber [是否包含数字]
         * @return [type]                 [description]
         */
        public static function get_rand_str($randLength=6, $addtime=0, $includenumber=1)
        {
            if ($includenumber)
                $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQEST123456789';
            $chars='abcdefghijklmnopqrstuvwxyz';
    
            $len = strlen($chars);
            $randStr = '';
            for ($i=0; $i<$randLength; $i++){
                $randStr .= $chars[rand(0, $len-1)];
            }
            $tokenvalue = $randStr;
            $addtime && $tokenvalue = $randStr . time();
            return $tokenvalue;
        }
    
        /** fengkui.net
         * [get_ip 定义一个函数get_ip() 客户端IP]
         * @return [type] [description]
         */
        public static function get_ip()
        {
            if (getenv("HTTP_CLIENT_IP"))
                $ip = getenv("HTTP_CLIENT_IP");
            else if(getenv("HTTP_X_FORWARDED_FOR"))
                $ip = getenv("HTTP_X_FORWARDED_FOR");
            else if(getenv("REMOTE_ADDR"))
                $ip = getenv("REMOTE_ADDR");
            else $ip = "Unknow";
    
            if(preg_match('/^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1 -9]?\d))))$/', $ip))
                return $ip;
            else
                return '';
        }
    }

    本文参考文档:
    1、微信支付 小程序 (v3)- PHP 完整后端代码
    2、PHP 微信小程序 微信支付 v3
    3、微信支付V3版本小程序支付 php签名,验签,数据解密代码分享(完整方法主参考)
    4、微信支付 API v3 回调通知 签名验证 PHPdemo有嘛?

    推荐:《PHP视频教程

    以上就是随着微信支付的升级,PHP微信支付类V3接口也来了的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:learnku,如有侵犯,请联系admin@php.cn删除
    专题推荐:PHP
    上一篇:使用PHP要如何操作Redis?基本操作方法介绍 下一篇:分享封装的一个PHP微信支付的类库(扫码、H5、小程序)
    大前端线上培训班

    相关文章推荐

    • 如何解决php无法加载memcache问题• php 多维数组怎么转为字符串• php5.6怎么设置时区• 使用PHP要如何操作Redis?基本操作方法介绍

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网