企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过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.csdn.net/detail/sinat_35861727/9858508 或者下载: http://download.csdn.net/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.csdn.net/detail/sinat_35861727/9858508 或者下载: http://download.csdn.net/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>