/** * 将xml转为array * @param string $xml xml字符串 * @return array 转换得到的数组 */ public function xml2array($xml) { //禁止引用外部xml实体 libxml_disable_entity_loader(false); $result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $result; } //用户退款 public function postXmlCurl($xml, $url, $useCert = false, $second = 60, $oid = 0, $source) { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); //如果有配置代理这里就设置代理 if ( WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" && WxPayConfig::CURL_PROXY_PORT != 0 ) { curl_setopt($ch, CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST); curl_setopt($ch, CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT); } curl_setopt($ch, CURLOPT_URL, $url); // curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//严格校验 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); //严格校验 //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if ($useCert == true && $source == 2) { //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT, PayConfig::get_wx_config_info('sslcert_path', $oid)); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY, PayConfig::get_wx_config_info('sslkey_path', $oid)); }elseif($useCert == true && $source == 5){ curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT, PayConfig::get_wx_config_info('wxGzhsslcert', $oid)); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY, PayConfig::get_wx_config_info('wxGzhsslkey', $oid)); } //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //运行curl $data = curl_exec($ch); //返回结果 if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); echo "call faild, errorCode:$error "; curl_close($ch); return false; } } /** * 将一个数组转换为 XML 结构的字符串 * @param array $arr 要转换的数组 * @param int $level 节点层级, 1 为 Root. * @return string XML 结构的字符串 */ public function array2xml($arr, $level = 1) { $s = $level == 1 ? "<xml>" : ''; foreach ($arr as $tagname => $value) { if (is_numeric($tagname)) { $tagname = $value['TagName']; unset($value['TagName']); } if (!is_array($value)) { $s .= "<{$tagname}>" . (!is_numeric($value) ? '<![CDATA[' : '') . $value . (!is_numeric($value) ? ']]>' : '') . "</{$tagname}>"; } else { $s .= "<{$tagname}>" . $this->array2xml($value, $level + 1) . "</{$tagname}>"; } } $s = preg_replace("/([x01-x08x0b-x0cx0e-x1f])+/", ' ', $s); return $level == 1 ? $s . "</xml>" : $s; } function wxrefund($order_id, $timeOut = 6) { //$order_id = input('orsid'); $order = StoreOd::where('order_num', $order_id)->find(); if (!$order) { return json(['code' => 2, 'data' => "", 'msg' => "无效订单号"]); } $refund_order = time() . rand(1000, 9999); //退款单号 /* $total_price = $order['price'] * 100; $refund_price = $order['price'] * 100; */ $total_price = 1; $refund_price = 1; if ($order['source'] == 2){ $merchid = PayConfig::get_wx_config_info('wxmch_id', $order['oid']); $appid = PayConfig::get_wx_config_info('wxappid', $order['oid']); $key = PayConfig::get_wx_config_info('wxkey', $order['oid']); } elseif ($order['source'] == 5){ $merchid = PayConfig::get_wx_config_info('wxGzhMch_id', $order['oid']); $appid = PayConfig::get_wx_config_info('wxGzhAppid', $order['oid']); $key = PayConfig::get_wx_config_info('wxGzhKey', $order['oid']); } $nonce_str = '' . strval(mt_rand(100000, 999999)); //随机字符串 $stra = "appid=" . $appid . "&mch_id=" . $merchid . "&nonce_str=" . $nonce_str . "&op_user_id=" . $merchid . "&out_refund_no=" . $refund_order . "&out_trade_no=" . $order['order_num'] . "&refund_fee=" . $refund_price . "&total_fee=" . $total_price . "&key=" . $key; $sign = strtoupper(md5($stra)); $param = [ 'appid' => $appid, 'mch_id' => $merchid, 'nonce_str' => $nonce_str, 'op_user_id' => $merchid, 'out_refund_no' => $refund_order, //商户退款单号 'out_trade_no' => $order['order_num'], 'refund_fee' => $refund_price, //退款金额 'total_fee' => $total_price, 'sign' => $sign ]; $xmldata = self::array2xml($param); //传入参数转换成xml格式 $url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; $res = self::postXmlCurl($xmldata, $url, true, $timeOut, $order['oid'], $order['source']); //curl发出请求 if (!$res) { return ['status' => 1, 'msg' => "服务器连接失败"]; } $content = self::xml2array($res); $data = ['out_refund_no' => $content['out_refund_no'], 'refund_id' => $content['refund_id'], 'refund_fee' => $content['refund_fee']]; if ($content['result_code'] == 'SUCCESS') { return json(['code' => 1, 'data' => $data, 'msg' => '操作成功']); } else { return json(['code' => 2, 'data' => '', 'msg' => '操作失败,' . $content['err_code_des']]); } }