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 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> PHP版微信V3支付-踩坑帮助 -> 正文阅读

[PHP知识库]PHP版微信V3支付-踩坑帮助

<?php

namespace app\repositories;

use think\facade\Db;

class WxpayRepository
{
     /*
     * 微信支付统一下单
     * @$name 订单名称
     * @$ordernumber 订单单号
     * @$money  金额
     * @$code  微信code
     * @$user_id  用户ID
    */
    public function wechartAddOrder($name, $ordernumber, $money, $code, $user_id)
    {
        $money = 1;

        $appid = env('WECHAT.appid');
        $secret = env('WECHAT.secret');
        $mchid = env('WECHAT.mch_id'); // 商户号
        $xlid = env('WECHAT.serial_number');//API序列号
        /*
         * 根据code获取openid
         * */
        $oauth2Url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $appid . "&secret=" . $secret . "&js_code=" . $code . "&grant_type=authorization_code";

        $oauth2 = httpGet($oauth2Url);
        $oauth2 = json_decode($oauth2, true);
        if (!isset($oauth2['openid'])) return show(config("status.error"), '失败', $oauth2, 200);

        $out_trade_no = order_id();//生成支付单号
        $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
        $urlarr = parse_url($url);
        $data = array();
        $randstr = getrandstr(16);//随机字符串长度不超过32
        $time = time();
        $data['appid'] = $appid;
        $data['mchid'] = $mchid;
        $data['description'] = $name;//商品描述
        $data['attach'] = $ordernumber;//订单编号
        $data['out_trade_no'] = $out_trade_no;//支付订单编号
        $data['notify_url'] = WEB_DOMAIN . "/" . env('PROJECT.projectName') . "/public/index.php/notify/payment_notify";//回调接口
        $data['amount']['total'] = $money;

        $data['payer']['openid'] = $oauth2['openid'];//用户付款的openID
        $data = json_encode($data);
        $key = $this->getSign($data, $urlarr['path'], $randstr, $time);//签名
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $randstr, $time, $key);//头部信息
        $header = array(
            'Content-Type:' . 'application/json; charset=UTF-8',
            'Accept:application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        );
        $ret = $this->curl_post_https($url, $data, $header);
        $ret = json_decode($ret, true);
        if (isset($ret['prepay_id'])) {
            $pay_data = array(
                'payment_status' => 0,
                'pay_type' => 2,
                'type' => 3,
                'payment_order_id' => $out_trade_no,
                'payment_fee' => $money,
                'consumer_id' => $user_id,
                'payment_apply_time' => $time,
                'order_id' => $ordernumber,
                'prepay_id' => $ret['prepay_id'],
            );
            Db::name('payment_list')->save($pay_data);

            $res['timeStamp'] = $time;//时间戳
            $res['nonceStr'] = $randstr;//随机字符串
            $res['signType'] = 'RSA';//签名算法,暂支持 RSA
            $res['package'] = 'prepay_id=' . $ret['prepay_id'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
            $res['paySign'] = $this->getWechartSign($appid,$time,$res['nonceStr'],$res['package']);//签名
            return $res;
        }
        return $ret;
    }

    /**
     * 申请退款API
     * @$name   订单商品名称
     * @$out_trade_no   订单号
     * @$money   订单退款金额
     * @$transaction_id  微信支付成功的流水单号
     */
    public function refundOrders($name, $out_trade_no, $transaction_id,$money)
    {
        $money = 1;
        $mchid = env('WECHAT.mch_id'); // 商户号
        $xlid = env('WECHAT.serial_number');//API序列号
        $url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
        $urlarr = parse_url($url);
        $data['transaction_id'] = $transaction_id;//原支付交易对应的微信订单号。
        $data['out_refund_no'] = $out_trade_no;//退款单号
        $data['reason'] = "订单". $name ."的退款";//退款单号
        $data['notify_url'] = WEB_DOMAIN . "/" . env('PROJECT.projectName') . "/public/index.php/notify/refund_notify";//退款回调接口
        $data['amount']['refund'] = $money;
        $data['amount']['total'] = $money;
        $data['amount']['currency'] = "CNY";

        $randstr = getrandstr(16);//随机字符串长度不超过32
        $time = time();
        $data = json_encode($data);
        $key = $this->getSign($data, $urlarr['path'], $randstr, $time);//签名

        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $randstr, $time, $key);//头部信息
        $header = array(
            'Content-Type:' . 'application/json; charset=UTF-8',
            'Accept:application/json',
            'User-Agent:*/*',
            'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token
        );

        $ret = $this->curl_post_https($url, $data, $header);
        $ret = json_decode($ret, true);
        return $ret;
    }


    /*
     * 统一下单之后前端需要的微信支付所需签名
     * 微信支付签名
     * */
    public function getSign($data = array(), $url, $randstr, $time)
    {
        $str = "POST" . "\n" . $url . "\n" . $time . "\n" . $randstr . "\n" . $data . "\n";
        $key = file_get_contents(root_path() . '/vendor/path/apiclient_key.pem');//在商户平台下载的秘钥
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    /*
     * 统一下单调起支付的签名
     * */
    public function getWechartSign($appid, $timeStamp, $noncestr, $prepay_id)
    {
        $str = $appid . "\n" . $timeStamp . "\n" . $noncestr . "\n" . $prepay_id . "\n";
        $key = file_get_contents(root_path() . '/vendor/path/apiclient_key.pem');//在商户平台下载的秘钥
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    /*
     * 签名方法
     * */
    public function getSha256WithRSA($content, $privateKey)
    {
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign = base64_encode($binary_signature);
        return $sign;
    }

    /*
     * POST请求方法
     * PHP CURL HTTPS POST
     * */
    public function curl_post_https($url, $data, $header)
    { // 模拟提交数据函数
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回

        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        $tmpInfo = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Errno' . curl_error($curl);//捕抓异常
        }
        curl_close($curl); // 关闭CURL会话
        return $tmpInfo; // 返回数据,json格式
    }

    /*
    * 微信支付回调
    * */
    public function payment_notify($request)
    {
        $input_data = $request->param();
        $payConfig = Db::name('pay_config')
            ->where('pay_type',1)
            ->where('type',4)
            ->find();
        if ($payConfig) {
            $key = $payConfig['key'];//商户平台设置的api v3 密码
        } else {
            $key = env('WECHAT.key');//商户平台设置的api v3 密码
        }
        $text = base64_decode($input_data['resource']['ciphertext']);

        $str = sodium_crypto_aead_aes256gcm_decrypt($text, $input_data['resource']['associated_data'], $input_data['resource']['nonce'], $key);

        $res = json_decode($str, true);
        if ($res['trade_state'] == 'SUCCESS') {
            Db::startTrans();
            try {
                /*
                 *
                 * 成功操作
                 * */


                Db::commit();

                $a = array(
                    "code" => "SUCCESS",
                    "message" => "成功"
                );
                return json_encode($a);
            } catch (\Exception $e) {
                Db::rollback();
                $a = array(
                    "code" => "ERROR",
                    "message" => "失败"
                );
                return json_encode($a);
            }
        }
        $a = array(
            "code" => "ERROR",
            "message" => "失败"
        );
        return json_encode($a);
    }

    /*
     * 微信退款回调
     * */
    public function refund_notify($request)
    {
        $input_data = $request->param();
        /*
         * 和支付回调一样的v3密码
         * */
        $key = env('WECHAT.key');//商户平台设置的api v3 密码

        $text = base64_decode($input_data['resource']['ciphertext']);
        $str = sodium_crypto_aead_aes256gcm_decrypt($text, $input_data['resource']['associated_data'], $input_data['resource']['nonce'], $key);

        $res = json_decode($str, true);
        if ($res['refund_status'] == 'SUCCESS') {
            Db::startTrans();
            try {
                /*
                 *
                 * 回调处理逻辑内容
                 *
                 * */

                Db::commit();

                $a = array(
                    "code" => "SUCCESS",
                    "message" => "成功"
                );
                return json_encode($a);
            } catch (\Exception $e) {
                Db::rollback();
                $a = array(
                    "code" => "ERROR",
                    "message" => "失败"
                );
                return json_encode($a);
            }
        }
        $a = array(
            "code" => "ERROR",
            "message" => "失败"
        );
        return json_encode($a);
    }

}
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:22:59  更:2021-07-31 16:23:44 
 
开发: 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/26 2:31:45-

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