企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。 比如目前的保险行业向客户退保、给付、理赔。
企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”进行操作。https://pay.weixin.qq.com/
注意: 与商户微信支付收款资金并非同一账户,需要单独充值。企业付款需要证书。
说到代码实现,又不得不吐槽一下官方文档(https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2)和SDK(下载:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip)了,基本跟没有差不多,全靠程序猿自己摸索然后进行代码实现。
主要步骤:
(1)构造post请求的数据
(2)发送数据请求请求的curl函数,可以去官方下载:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip。下载完毕将证书改成自己的证书路径就可以了。
我将完整的代码封装成了一个类,可以直接引入项目更改一下配置参数就可以使用的,也可以参看文章 微信支付之公众号发红包和企业付款,源码下载: http://download.youkuaiyun.com/detail/sinat_35861727/9858508 或者下载: http://download.youkuaiyun.com/download/sinat_35861727/9956485
支付失败时返回的数据:
支付成功返回:
企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”进行操作。https://pay.weixin.qq.com/
注意: 与商户微信支付收款资金并非同一账户,需要单独充值。企业付款需要证书。
说到代码实现,又不得不吐槽一下官方文档(https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2)和SDK(下载:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip)了,基本跟没有差不多,全靠程序猿自己摸索然后进行代码实现。
主要步骤:
(1)构造post请求的数据
这个,需要哪些参数可以参照文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2,我根据文档构造方法如下:
- /**
- * 企业支付
- * @param string $openid 用户openID
- * @param string $trade_no 单号
- * @param string $money 金额
- * @param string $desc 描述
- * @return string XML 结构的字符串
- */
- public function pay($openid,$trade_no,$money,$desc){
- $data = array(
- 'mch_appid' => WxPayConfig::APPID,
- 'mchid' => WxPayConfig::MCHID,
- 'nonce_str' => self::getNonceStr(),
- //'device_info' => '1000',
- 'partner_trade_no' => $trade_no, //商户订单号,需要唯一
- 'openid' => $openid,
- 'check_name'=> 'NO_CHECK', //OPTION_CHECK不强制校验真实姓名, FORCE_CHECK:强制 NO_CHECK:
- //'re_user_name' => 'jorsh', //收款人用户姓名
- 'amount' => $money * 100, //付款金额单位为分
- 'desc' => $desc,
- 'spbill_create_ip' => self::getip()
- );
- //生成签名
- $data['sign'] = self::makeSign($data);
- //构造XML数据
- $xmldata = self::array2xml($data);
- $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
- //发送post请求
- $res = self::curl_post_ssl($url, $xmldata);
- if(!$res){
- return array('status'=>1, 'msg'=>"Can't connect the server" );
- }
- // 这句file_put_contents是用来查看服务器返回的结果 测试完可以删除了
- file_put_contents(APP_ROOT.'/Api/wxpay/logs/log2.txt',$res,FILE_APPEND);
- //付款结果分析
- $content = self::xml2array($res);
- if(strval($content['return_code']) == 'FAIL'){
- return array('status'=>1, 'msg'=>strval($content['return_msg']));
- }
- if(strval($content['result_code']) == 'FAIL'){
- return array('status'=>1, 'msg'=>strval($content['err_code']),':'.strval($content['err_code_des']));
- }
- $resdata = array(
- 'return_code' => strval($content['return_code']),
- 'result_code' => strval($content['result_code']),
- 'nonce_str' => strval($content['nonce_str']),
- 'partner_trade_no' => strval($content['partner_trade_no']),
- 'payment_no' => strval($content['payment_no']),
- 'payment_time' => strval($content['payment_time']),
- );
- return $resdata;
- }
(2)发送数据请求请求的curl函数,可以去官方下载:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip。下载完毕将证书改成自己的证书路径就可以了。
- /**
- * 企业付款发起请求
- * 此函数来自:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip
- */
- public function curl_post_ssl($url, $xmldata, $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,false);
- //以下两种方式需选择一种
- //第一种方法,cert 与 key 分别属于两个.pem文件
- //默认格式为PEM,可以注释
- curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
- curl_setopt($ch,CURLOPT_SSLCERT,WxPayConfig::SSLCERT_PATH);
- //默认格式为PEM,可以注释
- curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
- curl_setopt($ch,CURLOPT_SSLKEY,WxPayConfig::SSLKEY_PATH);
- //第二种方式,两个文件合成一个.pem文件
- //curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');
- if( count($aHeader) >= 1 ){
- curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
- }
- curl_setopt($ch,CURLOPT_POST, 1);
- curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata);
- $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;
- }
- }
我将完整的代码封装成了一个类,可以直接引入项目更改一下配置参数就可以使用的,也可以参看文章 微信支付之公众号发红包和企业付款,源码下载: http://download.youkuaiyun.com/detail/sinat_35861727/9858508 或者下载: http://download.youkuaiyun.com/download/sinat_35861727/9956485
调用就超级简单了,引入项目之后就直接调用:
- //测试支付
- public function test(){
- $openid = 'ovprvtzBZaWXnZUadwgexOLNc93M';
- $trade_no = date('YmdHis').mt_rand(1000,9999);
- $res = self::pay($openid,$trade_no,1,'提现');
- return $res;
- }
- //引入企业付款类
- require_once APP_ROOT.'/Api/merchpay.class.php';
- $merch = new \MerchPay();
- $res = $merch->test();
- print_r($res);
- <xml>
- <return_code><![CDATA[SUCCESS]]></return_code>
- <return_msg><![CDATA[支付失败]]></return_msg>
- <mch_appid><![CDATA[wx09e38d3dcca919a4]]></mch_appid>
- <mchid><![CDATA[1314969701]]></mchid>
- <result_code><![CDATA[FAIL]]></result_code>
- <err_code><![CDATA[AMOUNT_LIMIT]]></err_code>
- <err_code_des><![CDATA[付款金额超出限制。低于最小金额1.00元或累计超过20000.00元。]]></err_code_des>
- </xml>
- <xml>
- <return_code><![CDATA[SUCCESS]]></return_code>
- <return_msg><![CDATA[]]></return_msg>
- <nonce_str><![CDATA[kxm3zzlobtmb90rfodfejhug6qfosstl]]></nonce_str>
- <result_code><![CDATA[SUCCESS]]></result_code>
- <partner_trade_no><![CDATA[201706011750279780]]></partner_trade_no>
- <payment_no><![CDATA[1000018301201706017928874552]]></payment_no>
- <payment_time><![CDATA[2017-06-01 17:50:28]]></payment_time>
- </xml>
