微信企业支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2

企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。
比如目前的保险行业向客户退保、给付、理赔。

企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”进行操作。

 

 

下面是微信企业付款接口THINKPHP控制器,

C('WX_APPID'),C('WX_MCHID'),C('WX_KEYC') 这三项我已事先写在配置文件中了

<?php
/**
 * 微信企业付款接口
 */
namespace Admin\Controller;
use Think\Controller;
class CompayController extends Controller {

    protected $payurl   = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';


    //这里的路径很重要  一定要写相对路径
    protected $cacab =  array(
        'api_cert'=>'weixin/cert/apiclient_cert.pem',
        'api_key'=>'weixin/cert/apiclient_key.pem',
        'api_ca'=>'weixin/cert/rootca.pem',
    );



    //$data 要传递的参数, $wxchat微信企业支付等信息
    /** $data 格式如下
     *  $data = array(
            'userid' //申请退款者ID
            'openid' //退款者openid
            'refundid' //退款申请ID
            'money' //退款金额
            'desc'  //退款描述
        );
     *
     */
    public function wxbuild($data, $wxchat){
        //判断有没有CA证书及支付信息
        if(empty($wxchat['api_cert']) || empty($wxchat['api_key']) || empty($wxchat['api_ca']) || empty($wxchat['appid']) || empty($wxchat['mchid'])){
            $wxchat['appid'] = C('WX_APPID'); //appid
            $wxchat['mchid'] = C('WX_MCHID'); //商户号
            $wxchat['api_cert'] = $this->cacab['api_cert'];
            $wxchat['api_key'] = $this->cacab['api_key'];
            $wxchat['api_ca'] = $this->cacab['api_ca'];
        }
        $webdata = array(
            'mch_appid' => $wxchat['appid'],
            'mchid'     => $wxchat['mchid'],
            'nonce_str' => md5(time()),
            //'device_info' => '1000',
            'partner_trade_no'  => $data['bpno'], //商户订单号,需要唯一
            'openid'    => $data['openid'],
            'check_name'=> 'NO_CHECK', //OPTION_CHECK不强制校验真实姓名, FORCE_CHECK:强制 NO_CHECK:
            //'re_user_name' => 'jorsh', //收款人用户姓名
            'amount'    => $data['money'] * 100, //付款金额单位为分
            'desc'      => empty($data['desc'])? '微信提现' : $data['desc'],
            'spbill_create_ip' => $this->getip(),
        );
        $sig = $this->makeSign($webdata);

        foreach ($webdata as $k => $v) {
            $tarr[] =$k.'='.$v;
        }
        sort($tarr);
        $sign = implode($tarr, '&');
        $sign .= '&key='.C('WX_KEYC');   //支付密钥
        //$webdata['sign']=strtoupper(md5($sign));
        $webdata['sign']= $sig;
        $wget = $this->array2xml($webdata);

        
        $content = $this->curl_post_ssl($this->payurl, $wget, $wxchat);
        if(!$content){
            return array('status'=>1, 'msg'=>"Can't connect the server" );
        }
        return $this->xmlToArray($content);
    }
 
    public function getip() {
        static $ip = '';
        $ip = $_SERVER['REMOTE_ADDR'];
        if(isset($_SERVER['HTTP_CDN_SRC_IP'])) {
            $ip = $_SERVER['HTTP_CDN_SRC_IP'];
        } elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
            foreach ($matches[0] AS $xip) {
                if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
                    $ip = $xip;
                    break;
                }
            }
        }
        return $ip;
    }
 
        /**
     * 将一个数组转换为 XML 结构的字符串
     * @param array $arr 要转换的数组
     * @param int $level 节点层级, 1 为 Root.
     * @return string XML 结构的字符串
     */
    public function array2xml($arr, $level = 1) {
        $s = $level == 1 ? "<xml>" : '';
        foreach($arr as $tagname => $value) {
            if (is_numeric($tagname)) {
                $tagname = $value['TagName'];
                unset($value['TagName']);
            }
            if(!is_array($value)) {
                $s .= "<{$tagname}>".(!is_numeric($value) ? '<![CDATA[' : '').$value.(!is_numeric($value) ? ']]>' : '')."</{$tagname}>";
            } else {
                $s .= "<{$tagname}>" . $this->array2xml($value, $level + 1)."</{$tagname}>";
            }
        }
        $s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
        return $level == 1 ? $s."</xml>" : $s;
    }

    /**
     * 微信支付发起请求
     */
    protected function curl_post_ssl($url, $xmldata,$wxchat, $second=30,$aHeader=array()){
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
        

        //这里设置代理,如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
        curl_setopt($ch, CURLOPT_SSLVERSION, 1);
        //默认格式为PEM,可以注释
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT,$wxchat['api_cert']);
        //默认格式为PEM,可以注释
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY,$wxchat['api_key']);
        //curl_setopt($ch,CURLOPT_CAINFO,$config['rootca']);
        if( count($aHeader) >= 1 ){
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); 
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);

        $data = curl_exec($ch);
        if($data){
            curl_close($ch);
            return $data;
        }else {
            $error = curl_errno($ch);
            echo "call faild, errorCode:$error\n";
            curl_close($ch);
            return false;
        }
    }

    //将XML转为array
    public function xmlToArray($xml)
    {    
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        
        return $values;
    }


    /**
    * 生成签名
    * @return 签名,本函数不覆盖sign成员变量
    */
    public function makeSign($data){
        //获取微信支付秘钥
        vendor('WxPayPubHelper.WxPayJsApiPay');
        $key = \WxPayConfig::KEY;
        // 去空
        $data=array_filter($data);
        //签名步骤一:按字典序排序参数
        ksort($data);
        $string_a=http_build_query($data);
        $string_a=urldecode($string_a);
        //签名步骤二:在string后加入KEY
        //$config=$this->config;
        $string_sign_temp=$string_a."&key=".$key;
        //签名步骤三:MD5加密
        $sign = md5($string_sign_temp);
        // 签名步骤四:所有字符转为大写
        $result=strtoupper($sign);
        return $result;
    }

    //企业付款测试
    public function test(){
        $bpid = session('dpid');
        //通过bpid查询提现信息
        $balance = M('balance')->where('bpid ='.$bpid)->find();
        //通过用户ID获取OPENID
        $openid = M('userinfo')->where('uid ='.$balance['uid'])->getField('openid');
        $username = M('userinfo')->where('uid ='.$balance['uid'])->getField('username');
        $data = array(
            'userid' => $balance['uid'],       //用户ID   做更新状态使用
            'openid' => $openid,                //收钱的人微信 OPENID
            'refundid' => $balance['bpid'],     //提现申请IDbpno
            'bpno' => $balance['bpno'],        //提现申请ID
            'money'    => $balance['dzprice'], //金额
            'desc'     => '微信提现',
        );
        //var_dump($data);die;
        $res = $this->wxbuild($data);
        if ($res['result_code'] == "SUCCESS") {
            //微信提现成功
            $time = date("Y-m-d H:i:s");
            $cltime = time();
            M('balance')->where('bpid='.$bpid)->setField(array('isverified'=>'1','remarks'=>$time." 微信提现成功!",'cltime'=>$cltime));//1是同意
            session('bpid',NULL);
            $this->ajaxReturn("success");
        }else{
            $this->ajaxReturn("error");
        }

    }
 
}