| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- <?php
- /**
- * 微信企业付款服务
- * Class TransferService
- * Author SHUI
- * @package wxpay
- */
- define('WEIXIN_SDK_DIR', __DIR__);
- require_once WEIXIN_SDK_DIR . '/lib/WxPay.Config.php';
- class TransferService {
-
- const TRANSFER_API = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
- const QUERY_API = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo';
- /**
- * 企业付款
- *
- * @access public
- *
- * @param string $openid 微信用户OPENID
- * @param float $amount 付款金额
- * @param string $orderid 订单号
- * @param string $ip 来源IP
- *
- * @return array
- */
- public function transfer($openid, $amount, $orderid, $ip) {
- $param = [
- 'mch_appid' => WxPayConfig::APPID,
- 'mchid' => WxPayConfig::MCHID,
- 'nonce_str' => self::createNonceStr(),
- 'openid' => $openid,
- 'check_name' => 'NO_CHECK', // 校验用户姓名选项。NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名
- 're_user_name' => '', // 收款用户真实姓名(不支持给非实名用户打款)
- 'partner_trade_no' => $orderid,
- 'spbill_create_ip' => $ip,
- 'amount' => intval($amount * 100), // 单位 转为分
- 'desc' => '提现转账',
- ];
- $param['sign'] = self::getSign($param, WxPayConfig::KEY);
-
- $responseXml = $this->curlPost(self::TRANSFER_API, self::arrayToXml($param));
- if ( empty($responseXml) ) {
- return ['flag' => -1, 'msg' => '发送请求失败'];
- }
-
- $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
- if ( $unifiedOrder === false ) {
- return ['flag' => 1, 'msg' => '解析响应数据失败'];
- }
-
- if ( 'SUCCESS' != $unifiedOrder->return_code ) {
- return ['flag' => 2, 'msg' => "{$unifiedOrder->return_code}:{$unifiedOrder->return_msg}"];
- }
-
- if ( 'SUCCESS' != $unifiedOrder->result_code ) {
- $unifiedOrder->err_code_des = $this->resetErrCodeDes($unifiedOrder->err_code, $unifiedOrder->err_code_des);
-
- $msg = "{$unifiedOrder->err_code}:{$unifiedOrder->err_code_des}";
-
- $queryOrder = $this->query($orderid); // 查询确认订单状态
- if (in_array($queryOrder['flag'], [4,5]) ) {
- $msg = $queryOrder['msg'];
- } else if ( '0' == $queryOrder['flag'] ) {
- return ['flag' => 0, 'msg' => '付款成功', 'orderid' => $queryOrder['orderid']];
- }
-
- return ['flag' => 3, 'msg' => $msg];
- }
-
- return ['flag' => 0, 'msg' => '付款成功', 'orderid' => $unifiedOrder->partner_trade_no];
- }
-
- /**
- * 企业付款查询
- *
- * @access public
- *
- * @param string $orderid 订单号
- *
- * @return array
- */
- public function query($orderid) {
- $param = [
- 'mch_appid' => WxPayConfig::APPID,
- 'mchid' => WxPayConfig::MCHID,
- 'nonce_str' => self::createNonceStr(),
- 'partner_trade_no' => $orderid,
- ];
-
- $param['sign'] = self::getSign($param, WxPayConfig::KEY);
-
- $responseXml = $this->curlPost(self::QUERY_API, self::arrayToXml($param));
- if ( empty($responseXml) ) {
- return ['flag' => -1, 'msg' => '发送请求失败'];
- }
-
- $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
- if ( $unifiedOrder === false ) {
- return ['flag' => 1, 'msg' => '解析响应数据失败'];
- }
-
- if ( 'SUCCESS' != $unifiedOrder->return_code ) {
- return ['flag' => 2, 'msg' => "{$unifiedOrder->return_code}:{$unifiedOrder->return_msg}"];
- }
-
- if ( 'SUCCESS' != $unifiedOrder->result_code ) {
- $unifiedOrder->err_code_des = $this->resetErrCodeDes($unifiedOrder->err_code, $unifiedOrder->err_code_des);
-
- return ['flag' => 3, 'msg' => "{$unifiedOrder->err_code}:{$unifiedOrder->err_code_des}"];
- }
-
- if ( 'FAILED' == $unifiedOrder->status ) {
- return ['flag' => 4, 'msg' => "{$unifiedOrder->reason}"];
- }
-
- if ( 'PROCESSING' == $unifiedOrder->status ) {
- return ['flag' => 5, 'msg' => '转账处理中'];
- }
-
- return ['flag' => 0, 'msg' => '已经付款成功', 'orderid' => $unifiedOrder->partner_trade_no];
- }
-
- public function curlPost($url = '', $postData = '', $options = []) {
- if (is_array($postData)) {
- $postData = http_build_query($postData);
- }
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
- curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
-
- if (!empty($options)) {
- curl_setopt_array($ch, $options);
- }
- //https请求 不验证证书和host
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
- //默认格式为PEM,可以注释
- curl_setopt($ch,CURLOPT_SSLCERTTYPE, 'PEM');
- curl_setopt($ch,CURLOPT_SSLCERT, WEIXIN_SDK_DIR.'/cert/apiclient_cert.pem');
- //默认格式为PEM,可以注释
- curl_setopt($ch,CURLOPT_SSLKEYTYPE, 'PEM');
- curl_setopt($ch,CURLOPT_SSLKEY, WEIXIN_SDK_DIR.'/cert/apiclient_key.pem');
- $data = curl_exec($ch);
- curl_close($ch);
-
- return $data;
- }
-
- public static 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;
- }
-
- public static function createNonceStr($len = 24) {
- $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
-
- $str = '';
- for ($i = 0; $i < $len; $i++) {
- $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
- }
-
- return $str;
- }
-
- public static function getSign($param, $key) {
- ksort($param, SORT_STRING);
-
- $unSignStr = self::formatQueryParaMap($param, false);
- $signStr = strtoupper(md5($unSignStr . '&key=' . $key));
-
- return $signStr;
- }
-
- protected static function formatQueryParaMap($paraMap, $urlEncode = false) {
- $buff = '';
-
- ksort($paraMap);
-
- foreach ($paraMap as $k => $v) {
- if (null != $v && 'null' != $v) {
- if ($urlEncode) {
- $v = urlencode($v);
- }
- $buff .= $k . "=" . $v . "&";
- }
- }
-
- $reqPar = '';
-
- if (strlen($buff) > 0) {
- $reqPar = substr($buff, 0, strlen($buff) - 1);
- }
-
- return $reqPar;
- }
-
- protected static function resetErrCodeDes($errCode, $errCodeDes) {
- switch ($errCode) {
- case 'NOTENOUGH':
- $errCodeDes = '商户余额不足';
- break;
- }
-
- return $errCodeDes;
- }
- }
|