微信企业付款API接口使用
微信企业支付开发文档: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"); } } }