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 = ""; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . ""; } else { $xml .= "<" . $key . ">"; } } $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; } }