• php 微信支付企业付款


    1.所需参数

    字段名变量名必填示例值类型描述
    公众账号appid mch_appid wx8888888888888888 String 公众号的appId
    商户号 mchid 1900000109 String(32) 微信支付平台商户号
    就是平台账号
    随机字符串 nonce_str 5K8264ILTKCH16CQ2502SI8ZNMTM67VS String(32) 随机字符串,随便随机个什么<32位
    商户订单号 partner_trade_no 10000098201411111234567890 String 订单号,保持唯一性,自定义一个随机订单号
    用户
    openid
    openid oxTWIuGaIt6gTKsQRLau2M0yL16E String 商户appid下,某用户的openid
    校验用户姓名选项 check_name NO_CHECK
    不检验 (小额推荐)
    FORCE_CHEC
    强制检验
    OPTION_CHECK
    自动检验
    String NO_CHECK:不校验真实姓名 
    FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) 
    OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
    收款用户姓名 re_user_name 可选 马花花
    (如果上一个参数为强制检验此为必填项)
    String 收款用户真实姓名。 
    如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名
    金额 amount 100
    单位为分
    100就是100分.
    int 企业付款金额,单位为分
    企业付款描述信息 desc 奖金啊,提现成功啊
    退款成功啊什么的
    String 企业付款操作说明信息。必填。
    Ip地址 spbill_create_ip 192.168.0.1 String(32) 调用接口的机器Ip地址服务器ip
    支付密钥
    key
    F5YguNW77Ao4N5yu5wZ8Lb00NKO987ks
    String(32)
    设置在商户平台上的支付密钥
    签名
    sign
    C380BEC2BFD727A4B6845133519F3AD6
    String(32)
    上面的内容的一个综合的加密结果

    2.还需要支付时使用的证书

    3.签名的规则

    意思就是将上述的除了支付秘钥签名的9-10项(因为收款用户姓名是根据验证选项而决定是否需要的)

    按照ASCII的从小到大排序之后的字符串

    例如:$str = "amount=100&check_name=NO_CHECK&desc=奖金啊,提现成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=10000098201411111234567890&spbill_create_ip=192.168.0.1";

    1. 签名是不是一直变动的呢?是的 每一个签名都是不一样的,别想着存起来一直用!怎么算呢?官方有一个文档,对于会的人来说就是废话,对于不会的来说就是天书。总的来说分为3部,官方有一个签名生成工具https://pay.weixin.qq.com/wiki/tools/signverify/

      1. 将你本次请求的所有参数(当然除了签名),按照一定的顺序排序成一个字符串,顺序一会再说,先说格式,比如本次的这次请求有9个参数:

        $str = "amount=100&check_name=NO_CHECK&desc=奖金啊,提现成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=10000098201411111234567890&spbill_create_ip=192.168.0.1";

        仔细观察不难发现,字符串排列是有顺序的 为键值首字母的排列顺序。而官方为了听起来霸气,讲的是根据 参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式排序吓的我一哆嗦啊! 不就字母顺序表么!不过仔细一看发现不对了,比如 mchid和 mch_appid这尼玛前三个字母一样啊,一位一位排序下来出现一个 i 和 _怎么办呢? 这时候就用到ASCII码表了,不过看官也不用去查了 上面的可以直接粘去用了 而ASCII码表的顺序呢就是按照0123456789:;< = > ? @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [ ] ^ _ ` abcdefghijklmnopqrstuvwxyz { | }~的顺序排列 那么我门就知道mch_appid应该在 mchid 前面了。
      2. 排序完这9个参数 之后再用&加上特殊参数 微信支付平台上设置的支付密钥就是

        $str = "amount=100&check_name=NO_CHECK&desc=奖金啊,提现成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=10000098201411111234567890&spbill_create_ip=192.168.0.1&key=F5YguNW77Ao4N5yu5wZ8Lb00NKO987ks"
      3. 之后就简单了先md5加密下然后转为大写 签名就OK了

        $sign = strtoupper(md5($str));

               

            然后我们就要将这些参数填充到xml格式的字符串中去了

    4.开始撸码吧

            /**
         * 格式化参数格式化成url参数
         */
        public function ToUrl($arr)
        {
            $buff = "";
            foreach ($arr as $k => $v)
            {
                if($k != "sign" && $v != "" && !is_array($v)){
                    $buff .= $k . "=" . $v . "&";
                }
            }    
            $buff = trim($buff, "&");
            return $buff;
        }
            //将乱序的数组    
            public function ToSign($arr,$key)
        {
            //签名步骤一:按字典序排序参数
            ksort($arr);
            $string = ToUrl($arr);    
            //签名步骤二:在string后加入KEY
            $string = $string . "&key=".$key;
            //签名步骤三:MD5加密
            $string = md5($string);        
            //签名步骤四:所有字符转为大写
    //        $result1 = strtoupper($string);
            return $string;
        }
    /**
         * 输出xml字符
         * @throws WxPayException
        **/
        public static function ToXml($arr)
        {
            if(!is_array($arr) || count($arr) <= 0)
            {
                echo '数据异常';
        }     
            $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; 
        }
    /**
         * zll 生成唯一订单号
         */
        public function order_sn(){
            $str = "qyfk".uniqid();
            return $str;
        }
    /**
         * zll 将信息提交到微信服务器,发起企业付款
         */
        public function qyzf_post($url,$xml,$config,$second=30){
            $ch = curl_init();
            curl_setopt($ch,CURLOPT_TIMEOUT,$second);
            curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch,CURLOPT_URL,$url);
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
    //        curl_setopt($ch,CURLOPT_SSLCERT,"/home/lizi/addons/grow/template/mobile/cash/apiclient_cert.pem");
    //        curl_setopt($ch,CURLOPT_SSLKEY,"/home/lizi/addons/grow/template/mobile/cash/apiclient_key.pem");
            $str = 'D:/www/';//证书必须使用绝对路径,否则报错,错误貌似是52什么的
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT,$str.trim($config['apiclient_cert'],'.'));
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY,$str.trim($config['apiclient_key'],'.'));
            curl_setopt($ch,CURLOPT_POST, 1);
            curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
            $data = curl_exec($ch);
            if($data){
                curl_close($ch);
                return $data;
            }else{
                $error = curl_errno($ch);
                echo "call faild, errorCode:$error
    ";
                curl_close($ch);
                return false;
            }
        }
    /**
         * zll 企业付款
         */
        public function qiyezhifu($data){
            //解释amount为付款金额,单位分,貌似最低1元,desc为付款的描述(必填),ip就是服务器ip必填
            //$data = array('wxappid'=>14,'openid'=>'oRyzq0LrtuqKqQdH-FubBqcMuTi8-','amount'=>100,'desc'=>'提现奖励','ip'=>'123.207.19.254');
            
            
            //获取数据库的支付配置信息
            $config = get_pay_conf($data['wxappid']);
            if($config){
                //对必备参数进行有效性判断
                if(empty($config['appid']) || empty($config['shh']) || empty($config['partnerkey']) || empty($data['amount']) || empty($config['apiclient_cert']) || empty($config['apiclient_key'])){
                    throw new Exception("支付配置中的appid或商户号或支付秘钥不能为空,或支付金额不能为空");
                }else{
                    $da['mch_appid'] = $config['appid'];                //appid
                    $da['mchid'] = $config['shh'];                        //商户号
                    $da['nonce_str'] = $this->getStr(32);                //随机字符串
                    $da['partner_trade_no'] = $this->order_sn();        //订单号,保持唯一性即可
                    $da['openid'] = $data['openid'];                    //粉丝的openid
                    $da['check_name'] = "NO_CHECK";                        //NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
                    //$da['re_user_name'] = "";                            //收款用户真实姓名。 如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名
                    $da['amount'] = $data['amount'];                            //付款金额,单位分
                    $da['desc'] = $data['desc'] ? $data['desc']:"提现奖励";                            //企业付款描述信息
                    $da['spbill_create_ip'] = $data['ip'] ? $data['ip'] : "123.207.19.254";            //服务器ip
                    $da['sign'] = $this->ToSign($da, $config['partnerkey']);//生成签名
                    //$da['key'] = $config['partnerkey'];                    //支付秘钥
                    
                    //将数组转为xml
                    $xml = $this->ToXml($da);
                    $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
                    $this->qyzf_post($url,$xml,$config);
                }            
            }else{
                return false;
            }
        }

    上面的代码我是在thinkphp3.2框架里面写的,所以方法之间的调用用的是$this->XXX();

    其他的框架或原生的php可以进行修改方法调用方式即可

  • 相关阅读:
    iOS开发之视频播放
    iOS开发之Copy & MutableCopy及深复制 & 浅复制
    iOS开发之JSON & XML
    iOS开发之NSObject的多线程
    iOS开发之单例模式
    iOS开发之Run Loop
    taro开发微信小程序-页面开发规范
    视频Video放器的部分实例方法
    Input框搜索关键字高亮显示
    vue上拉加载下拉加载
  • 原文地址:https://www.cnblogs.com/zonglonglong/p/8523343.html
Copyright © 2020-2023  润新知