服务分帐功能实现
1、开通服务商分帐功能
2、添加子商户
3、开始分账 需要先添加可分账用户才能分
注意点:
1、在支付的时候添加 profit_sharing = 'Y'
2、签名和请求参数的签名类型为 HMAC-SHA256
3、需要证书
* 服务商分账功能
*
*/
class wxDivideAccount
{
protected $CertPem = '/home/wwwroot/xixxxxm/comxxxmon/mch/apiclient_cert.pem';
protected $KeyPem = '/home/wwwroot/xixxxxm/comxxxmon/mch/apiclient_key.pem';
protected $key = 'lwLyC2AWYPwwewewt4ddkX2vhO5q'; //支付密钥key
/*
服务商分账
*/
public function divideMoney()
{
$params = array();
$params['mch_id'] = '1406xx6102'; //服务商mch_id
$params['sub_mch_id'] = '1553xx6371'; //特约商户mch_id
$params['appid'] = 'wx18dbxxx55773c05'; //服务商对就的appid
$params['sub_appid'] = 'wx7814xxaddbeb8'; //对应的子appid
$params['nonce_str'] = $this->createNoncestr();
$params['sign_type'] = 'HMAC-SHA256';
$params['transaction_id'] = '4200000450201910195680876190'; //微信支付订单号
$params['out_order_no'] = '157146517126_580624809017106007'; //交易订单号
$receivers = array([
'type' => 'PERSONAL_SUB_OPENID',
'account' => 'owf034yN-8MdAFNgaNm4qbxDw', //sub_openid
'amount' => 20,
'description' => '分给推广员'
]);
$params['receivers'] = json_encode($receivers);
$params['sign'] = $this->createSign($params);
//把数组转化成xml格式
$xmlData = $this->arrayToXml($params);
$resXml = $this->postXmlCurl('https://api.mch.weixin.qq.com/secapi/pay/profitsharing',$xmlData,true);
$resXml = $this->xmlSafeStr(html_entity_decode($resXml));
$resData = json_decode(json_encode(simplexml_load_string($resXml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
if($resData['return_code']=='SUCCESS' && $resData['result_code']=='SUCCESS') return true;
write_log('分账失败,msg:'$resData['return_msg'],'profitshare');
return false;
}
//添加可分帐帐号
public function profitSharingAddreceiver()
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver';
$params = array();
$params['mch_id'] = '1406xx6102'; //服务商mch_id
$params['sub_mch_id'] = '1553xx6371'; //特约商户mch_id
$params['appid'] = 'wx18dbxxx55773c05'; //服务商对就的appid
$params['sub_appid'] = 'wx7814xxaddbeb8'; //对应的子appid
$params['nonce_str'] = $this->createNoncestr();
$params['sign_type'] = 'HMAC-SHA256';
$receiver = [
'type' => 'PERSONAL_SUB_OPENID',
'account' => 'owf0349GNSmFBkvJpxlG-92N62ZM',
'relation_type' => 'DISTRIBUTOR'
];
$params['receiver'] = json_encode($receiver);
$params['sign'] = $this->createSign($params);
//把数组转化成xml格式
$xmlData = $this->arrayToXml($params);
$resXml = $this->postXmlCurl($url,$xmlData,true);
$resData = json_decode(json_encode(simplexml_load_string($resXml, 'SimpleXMLElement', LIBXML_NOCDATA)), 1);
if($resData['return_code']=='SUCCESS' && $resData['result_code']=='SUCCESS') return true;
write_log('分账用户添加失败,msg:'$resData['return_msg'],'profitshare');
return false;
}
/*
* 查询分账结果
*/
public function profitSharingQuery()
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingquery';
$params = array();
$params['mch_id'] = '1406xx6102';
$params['sub_mch_id'] = '1553xx6371';
$params['nonce_str'] = $this->createNoncestr();
$params['sign_type'] = 'HMAC-SHA256';
$params['transaction_id'] = '4200000450201910195680876190';
$params['out_order_no'] = '157146517126_580624809017106007';
$params['sign'] = $this->createSign($params);
//把数组转化成xml格式
$xmlData = $this->arrayToXml($params);
$resXml = $this->postXmlCurl($url,$xmlData,true);
$resXml = $this->xmlSafeStr(html_entity_decode($resXml));
$resData = json_decode(json_encode(simplexml_load_string($resXml, 'SimpleXMLElement', LIBXML_NOCDATA)), 1);
if($resData['return_code']=='SUCCESS' && $resData['result_code']=='SUCCESS') return true;
write_log('分红查询 到账失败,msg:'$resData['return_msg'],'profitshare');
return false;
}
//生成签名
private function createSign($params)
{
//签名步骤一:按字典序排序参数
ksort($params);
$String = $this->formatBizQueryParaMap($params, false);
//签名步骤二:在string后加入KEY
$String = $String."&key=".$this->key;
//签名步骤三:加密方式HMAC-SHA256
// $String = md5($String);
$String = hash_hmac("sha256", $String,$this->key);
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}
//按字典序排序参数
private function formatBizQueryParaMap($params,$urlencode=false)
{
ksort($params);
$buff = '';
foreach($params as $key=>$val)
{
$buff .= $key . "=" . $val . "&";
}
$reqPar = substr($buff, 0, strlen($buff)-1);
return $reqPar;
}
//随机字符串
private function createNoncestr($length=32)
{
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$str = '';
for($i=0;$i<$length;$i++){
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
//将数组转换为xml格式
private function arrayToXml($arr)
{
$xml = "";
foreach($arr as $key=>$val)
{
if(is_numeric($val))
$xml .= '<' . $key .'>' . $val . '' . $key . '>';
else
$xml .= "<".$key.">".$key.">";
}
$xml .=" ";
return $xml;
}
private function postXmlCurl($url,$xml,$useCert=false, $second = 30)
{
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if($useCert)
{
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, $this->CertPem);
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, $this->KeyPem);
}
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);
set_time_limit(0);
//运行curl
$data = curl_exec($ch);
//返回结果
if ($data) {
curl_close($ch);
// write_log($data,'wxpay');
return $data;
} else {
// var_dump($data);
$error = curl_errno($ch);
write_log("curl出错,错误码:$error",'wxpay');
curl_close($ch);
return false;
}
}
/**
* 过滤特殊字符
* @param string $str
* @return string
*/
function xmlSafeStr($str)
{
return preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/", '', $str);
}