微信服务商分账功能

21次阅读

共计 5407 个字符,预计需要花费 14 分钟才能阅读完成。

服务分帐功能实现
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 = "<xml>";
           foreach($arr as $key=>$val)
           {if(is_numeric($val))
                   $xml .= '<' . $key .'>' . $val . '</' . $key . '>';
               else
                   $xml .= "<".$key."><![CDATA[".$val."]]></".$key.">";
           }

           $xml .="</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); 
       }
       

正文完
 0