IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 微信V3支付 php版本 -> 正文阅读

[移动开发]微信V3支付 php版本

<?php
//微信V3支付
class Wxpay
{


    private static $appid = 'xxxxxxxxxxxxxx'; //appid
    private static $mchid = 'xxxxxxxxxxxxxx'; //商户号
    private static $mch_apiv3key = 'xxxxxxxxxxxxxx'; //商户平台apiv3密钥(商户平台手动生成)
    private static $serial_no = 'xxxxxxxxxxxxxx';//商户API证书序列号serial_no
    private static $wx_serial_no = 'xxxxxxxxxxxxxx';//平台证书序列号
    


    /*
     * 支付(小程序支付)
     * @param type $sn        订单编号
     * @param type $money  金额
     * @param type $openid  用户小程序openid
     * @return type
     */


    public static function getPayParam($sn, $money, $openid)
    {
        $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi';
        $notify_url = url('/api/weixin/notify');


        $data = [];
        $data['appid'] = self::$appid;
        $data['mchid'] = self::$mchid; //商户号
        $data['description'] = 'xxx'; //描述?
        $data['out_trade_no'] = $sn; //商户系统内部订单号
        $data['time_expire'] = date('Y-m-d') . 'T' . date('H:i:s', (time() + 1800)) . '+08:00'; //订单失效时间2018-06-08T10:34:56+08:00
        $data['notify_url'] = $notify_url; //异步通知接口地址
        $data['amount'] = ['total' => $money * 100, 'currency' => 'CNY']; //金额
        $data['payer'] = ['openid' => $openid]; //用户


        $re = self::wxCurl($url, $data, 'POST');


        if (!isset($re['prepay_id'])) {
            exit('参数获取失败');
        }


        $result = [];
        $result['appId'] = self::$appid;
        $result['timeStamp'] = (string)time();
        $result['nonceStr'] = uniqid();
        $result['package'] = 'prepay_id=' . $re['prepay_id'];
        $result['signType'] = 'RSA';
        $result['paySign'] = self::getPaySign($result);


        return $result;
    }


    /**
     * 查询订单
     * @param type $sn
     */
    public static function select($sn, $return = false)
    {
        $mchid = self::$mchid; //商户号
        $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/' . $sn . '?mchid=' . $mchid;
        $re = self::wxCurl($url, [], 'GET');
        if ($return) {
            return $re;
        }
        if (isset($re['trade_state']) && $re['trade_state'] == 'SUCCESS') {
            return true;
        }
        return false;
    }


    /**
     * 关闭订单
     * @param type $sn
     */
    public static function close($sn)
    {
        $mchid = self::$mchid; //商户号
        $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/' . $sn . '/close';
        $re = self::wxCurl($url, ['mchid' => $mchid], 'POST');
        return true;
    }


    /**
     * 退款
     * @param type $sn
     */
    public static function refund($order_sn, $refund_sn, $total, $refund, $msg = '退款')
    {
        $url = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
        $data = [];
        $data['notify_url'] = url('ag/weixin/notify_refund');
        $data['out_trade_no'] = $order_sn; //订单号
        $data['out_refund_no'] = $refund_sn; //退款单号
        $data['reason'] = $msg;
        $data['amount'] = ['refund' => $refund * 100, 'total' => $total * 100, 'currency' => 'CNY'];
        $re = self::wxCurl($url, $data, 'POST');
        return $re;
    }


    //请求
    public static function wxCurl($url, $data = [], $method = 'GET')
    {
        $Authorization = self::getReSign($url, $data, $method);
        $header = [
            'Content-Type: application/json',
            'Accept: application/json',
            'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.63',
            'Authorization: ' . $Authorization
        ];


        $redata = $data ? json_encode($data) : '';


        //CURL
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        //有post参数-设置   
        if ($method=='POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $redata);
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        $result = curl_exec($ch);
        curl_close($ch);


        return $result ? json_decode($result, true) : [];
    }


    //后端请求签名
    public static function getReSign($url, $data, $method = 'GET')
    {
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $http_method = $method;
        $timestamp = time();
        $nonce = uniqid();
        $body = $data ? json_encode($data) : '';
        $mchid = self::$mchid; //商户id
        $serial_no = self::$serial_no; //证书编号
        $private_key = self::getPrivateKey(BASE_PATH . 'cert/apiclient_key.pem'); //商户私钥


        $message = $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";


        openssl_sign($message, $raw_sign, $private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);


        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $nonce, $timestamp, $serial_no, $sign);
        return 'WECHATPAY2-SHA256-RSA2048 ' . $token;
    }


    //前端小程序签名
    public static function getPaySign($result)
    {
        $private_key = self::getPrivateKey(BASE_PATH . 'cert/apiclient_key.pem'); //商户私钥
        $message = $result['appId'] . "\n" .
            $result['timeStamp'] . "\n" .
            $result['nonceStr'] . "\n" .
            $result['package'] . "\n";
        openssl_sign($message, $raw_sign, $private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        return $sign;
    }


    //验证签名
    public static function checkSign()
    {
        $header = $_SERVER;//请求头
        $serial_no = $header['wechatpay-serial'] ?? ''; //微信平台序列号
        $timeStamp = $header['wechatpay-timestamp'] ?? '';
        $nonce = $header['wechatpay-nonce'] ?? '';
        $body = file_get_contents('php://input');//获取原始请求体
        $wx_sign = $header['wechatpay-signature'] ?? '';
        $wx_serial_no = self::$wx_serial_no; //保存的平台序列号(从下载的平台证书里面获取)
        if (!$serial_no || $wx_serial_no != $serial_no) {//证书过期
            return false;
        }


        $message = $timeStamp . "\n" .
            $nonce . "\n" .
            $body . "\n";


        $wx_sign = base64_decode($wx_sign);
        $public_key = self::getPublicKey(BASE_PATH . 'cert/wx_public_cert.pem'); //平台公钥
        $res = openssl_verify($message, $wx_sign, $public_key, OPENSSL_ALGO_SHA256);
        if ($res == 1) {
            return true;
        }
        return false;
    }


    //获取私钥
    public static function getPrivateKey($filepath)
    {
        return openssl_get_privatekey(file_get_contents($filepath));
    }


    //获取公钥
    public static function getPublicKey($filepath)
    {
        return openssl_pkey_get_public(file_get_contents($filepath));
    }


    //加密数据(基本用不上)
    public static function getEncrypt($str)
    {
//$str是待加密字符串 
        $public_key_path = BASE_PATH . 'cert/wx_public_cert.pem'; //'平台证书路径';
        $public_key = file_get_contents($public_key_path);
        $encrypted = '';
        if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
            //base64编码 
            $sign = base64_encode($encrypted);
        } else {
            throw new Exception('encrypt failed');
        }
        return $sign;
    }


    //解密数据(下载证书用的)
    public static function decryptToString($ciphertext, $associatedData, $nonceStr)
    {
        $aesKey =self::$mch_apiv3key; //商户apiv3密钥解密
        $str = base64_decode($ciphertext);
        if (strlen($str) <= 16) {
            return '';
        }
        // ext-sodium (default installed on >= PHP 7.2) 如果没有该函数需要安装sodium扩展
        return sodium_crypto_aead_aes256gcm_decrypt($str, $associatedData, $nonceStr, $aesKey);
    }


    //下载平台证书
    public static function downCert()
    {
        $url = 'https://api.mch.weixin.qq.com/v3/certificates';
        $re = self::wxCurl($url, [], 'GET');
        if (!isset($re['data'])) {
           exit('获取证书失败');
        }
        $ciphertext = $re['data'][0]['encrypt_certificate']['ciphertext'];
        $associatedData = $re['data'][0]['encrypt_certificate']['associated_data'];
        $nonceStr = $re['data'][0]['encrypt_certificate']['nonce'];
        $data = self::decryptToString($ciphertext, $associatedData, $nonceStr);
        if (!$data) {
            exit('获取证书解密失败');
        }
        //保存平台证书 (https://myssl.com/cert_decode.html)获取证书序列号
        file_put_contents(BASE_PATH . '/cert/wx_public_cert.pem', $data);
        return $data;
    }


}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:30:36  更:2021-11-20 18:33:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:52:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码