lhm166

微信企业支付开发文档: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");
        }

    }
 
}

 

分类:

技术点:

相关文章: