PHP开发微信消费者投诉2.0接口

PHP开发微信消费者投诉2.0接口,实现在商城管理后台查看并处理消费者投诉。

基本逻辑:

1.调用【创建回调地址】接口创建通知回调,当有新的投诉事件发生、投诉状态发生变化时,商户会收到通知回调;

2.调用【回调报文解密】解密通知回调报文,获取通知参数,可以根据获取到的投诉单号和动作类型判断该通知回调是否已接收,因为同样的通知可能会多次发送;

3.根据获取到投诉单号调用【查询投诉单详情】接口获取投诉单详情,里面的投诉人联系方式是加密的,如果需要用到可以调用【敏感信息解密】接口解密获取联系方式;

4.....目前需求只到这里,后续会继续更新

下面是使用到的相关代码:

    protected array $config = [];//配置信息


    public function __construct()
    {
        $this->config = ...;//获取配置信息
    }


    /**
     * @notes 生成签名
     * @param $url //请求URL
     * @param $http_method //请求方式
     * @param $data //请求参数
     * @param $apiclient_cert //微信支付证书
     * @param $apiclient_key //微信支付证书密钥
     * @param $mch_id //微信支付商户号
     * @return string
     */
    public function token($url,$http_method,$data,$apiclient_cert,$apiclient_key,$mch_id)
    {
        $url_parts = parse_url($url);//获取请求的绝对URL
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $timestamp = time();//系统当前时间戳
        $nonce = $timestamp.rand('10000','99999');//请求随机串
        $body = empty($data) ? '' : json_encode((object)$data);//请求报文主体

        $apiclient_cert_arr = openssl_x509_parse(file_get_contents($apiclient_cert));
        $serial_no          = $apiclient_cert_arr['serialNumberHex'];//证书序列号
        $mch_private_key    = file_get_contents($apiclient_key);//密钥
        $merchant_id = $mch_id;//商户id

        $message = $http_method."\n".
            $canonical_url."\n".
            $timestamp."\n".
            $nonce."\n".
            $body."\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);//签名值

        $schema = 'WECHATPAY2-SHA256-RSA2048';//认证类型
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);//签名信息

        return $schema.' '.$token;
    }

    /**
     * @notes 发送请求
     * @param $url //请求URL
     * @param $http_method //请求方式
     * @param $data //请求参数
     * @param $token //签名
     * @return bool|string
     */
    public function request($url,$http_method,$data,$token)
    {
        $curl = curl_init();//初始化
        curl_setopt($curl, CURLOPT_URL, (string)$url);//需要获取的URL地址
        if ($http_method == 'POST'){
            curl_setopt($curl, CURLOPT_POST, true);//启用时会发送一个常规的POST请求,类型为:application/x-www-form-urlencoded,就像表单提交的一样。
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);//全部数据使用HTTP协议中的"POST"操作来发送。
        }
        if ($http_method == 'PUT'){
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");//使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请求。
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);//全部数据使用HTTP协议中的"POST"操作来发送。
        }
        if ($http_method == 'DELETE'){
            curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');//使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请求。
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
        //添加请求头
        //微信支付API v3使用JSON作为消息体的数据交换格式。请求须设置HTTP头部:
        $headers = [
            'Authorization:'.$token,
            'Accept: application/json',
            'Content-Type: application/json',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        ];
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//设置HTTP头字段
        $output = curl_exec($curl);//抓取URL并把它传递给浏览器
        curl_close($curl);//关闭cURL资源,并且释放系统资源
        return $output;
    }

    /**
     * @notes 回调报文解密
     * @param $associatedData //附加身份验证数据
     * @param $nonceStr //随机数
     * @param $ciphertext //密文
     * @return false|string
     * @throws \SodiumException
     */
    public function decryptToString($associatedData,$nonceStr,$ciphertext)
    {
        $apiv3Key = $this->config['apiv3_key'];//Apiv3密钥

        $ciphertext = \base64_decode($ciphertext);
        if (strlen($ciphertext) <= 16) {
            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, $apiv3Key);
        }

        // 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, $apiv3Key);
        }

        // openssl (PHP >= 7.1 support AEAD)
        if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -16);
            $authTag = substr($ciphertext, -16);

            return \openssl_decrypt($ctext, 'aes-256-gcm', $apiv3Key, \OPENSSL_RAW_DATA, $nonceStr,
                $authTag, $associatedData);
        }

        throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
    }

    /**
     * @notes 查询投诉单详情
     * @param $complaint_id //投诉单对应的投诉单号
     * @return mixed
     */
    public function complaintDetail($complaint_id)
    {
        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaints-v2/'.$complaint_id;
        //请求方式
        $http_method = 'GET';
        //请求参数
        $data = [];

        $token  = self::token($url,$http_method,$data,$this->config['cert_path'],$this->config['key_path'],$this->config['mch_id']);//获取签名
        $result = self::request($url,$http_method,json_encode($data),$token);//发送请求
        return json_decode($result,true);
    }

    /**
     * @notes 创建回调地址
     * @param $token_url//回调地址
     * @return mixed
     */
    public function createTokenUrl($token_url)
    {
        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        //请求方式
        $http_method = 'POST';
        //请求参数
        $data = [
            'url' => $token_url,//通知地址
        ];

        $token  = self::token($url,$http_method,$data,$this->config['cert_path'],$this->config['key_path'],$this->config['mch_id']);//获取签名
        $result = self::request($url,$http_method,json_encode($data),$token);//发送请求
        return json_decode($result,true);
    }

    /**
     * @notes 查询回调地址
     * @return mixed
     */
    public function queryTokenUrl()
    {
        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        //请求方式
        $http_method = 'GET';
        //请求参数
        $data = [];

        $token  = self::token($url,$http_method,$data,$this->config['cert_path'],$this->config['key_path'],$this->config['mch_id']);//获取签名
        $result = self::request($url,$http_method,json_encode($data),$token);//发送请求
        return json_decode($result,true);
    }

    /**
     * @notes 更新回调地址
     * @param $token_url//回调地址
     * @return mixed
     */
    public function updateTokenUrl($token_url)
    {
        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        //请求方式
        $http_method = 'PUT';
        //请求参数
        $data = [
            'url' => $token_url,//通知地址
        ];

        $token  = self::token($url,$http_method,$data,$this->config['cert_path'],$this->config['key_path'],$this->config['mch_id']);//获取签名
        $result = self::request($url,$http_method,json_encode($data),$token);//发送请求
        return json_decode($result,true);
    }

    /**
     * @notes 删除回调地址
     * @return mixed
     */
    public function deleteTokenUrl()
    {
        //请求URL
        $url = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        //请求方式
        $http_method = 'DELETE';
        //请求参数
        $data = [];

        $token  = self::token($url,$http_method,$data,$this->config['cert_path'],$this->config['key_path'],$this->config['mch_id']);//获取签名
        $result = self::request($url,$http_method,json_encode($data),$token);//发送请求
        return json_decode($result,true);
    }

    /**
     * @notes 敏感信息解密
     * @param $waitDecrypt //待解密信息
     * @return mixed
     */
    public function getDecrypt($waitDecrypt)
    {
        $apiclient_key = $this->config['key_path'];//微信支付证书密钥
        $privateKey = openssl_get_privatekey(file_get_contents($apiclient_key));
        openssl_private_decrypt(base64_decode($waitDecrypt),$decrypted,$privateKey, OPENSSL_PKCS1_OAEP_PADDING);
        return $decrypted;
    }

注意:

1.通知回调地址,仅支持https;

2.同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

微信开发文档链接:微信支付-开发者文档

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值