where('store_id',$stoid)->field('appid,mchid,mchkey')->find(); if($source_type==1){ //---如果订单的来源是小程序的时候--- $path_wxapp= BASE_PATH . 'public/cert/' . $stoid . '/wxapp'; $conf_app_value = M("weapp")->where('store_id', $stoid)->field('appid,mchid,mchkey')->find(); if($config_value['mchid']!=$conf_app_value['mchid']){ $config_value=$conf_app_value; $path=$path_wxapp; } } $appid = $config_value['appid']; // * APPID:绑定支付的APPID(必须配置,开户邮件中可查看) $mchid = $config_value['mchid']; // * MCHID:商户号(必须配置,开户邮件中可查看) $key = $config_value['mchkey']; // KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置) $out_trade_no = $ordno; $input = new input_data(); $input->SetAppid($appid);//公众账号ID $input->SetMch_id($mchid);//商户号 $nonce_str=$input->getNonceStr(); $input->SetNonce_str($nonce_str);//随机字符串 $input->SetData("partner_trade_no", $ordno); $input->SetData("openid", $openid); $input->SetData("check_name", 'FORCE_CHECK'); $input->SetData("re_user_name",$name); $input->SetData("amount", $money*100); $input->SetData("desc", "提现"); $input->SetData("spbill_create_ip", serverIP()); //传入服务器IP $url="https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; $input->SetSign($key);//签名 $xml = $input->ToXml(); $startTimeStamp = $input->getMillisecond();//请求开始时间 mlog('提现IP:'.serverIP().",支付商户号:".$mchid,'tixian/'.$stoid); $response = $input->postXmlCurl($xml, $url, true, 12,$path); $result =$input-> xmltoarray($response); mlog('提现结果:'.$response,'tixian/'.$stoid); return $result; } } class input_data{ protected $values = array(); /** * 设置参数 * @param string $key * @param string $value */ public function SetData($key, $value) { $this->values[$key] = $value; } /** * 设置微信分配的公众账号ID * @param string $value **/ public function SetAppid($value) { $this->values['mch_appid'] = $value; } /** * 设置微信支付分配的商户号 * @param string $value **/ public function SetMch_id($value) { $this->values['mchid'] = $value; } /** * 设置随机字符串,不长于32位。推荐随机数生成算法 * @param string $value **/ public function SetNonce_str($value) { $this->values['nonce_str'] = $value; } /** * * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public static function getNonceStr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } /** * 生成签名 * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值 */ public function SetSign($key) { //签名步骤一:按字典序排序参数 ksort($this->values); $string = $this->ToUrlParams(); //签名步骤二:在string后加入KEY $string = $string . "&key=".$key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); $this->values['sign'] = $result; return $result; } /** * 获取毫秒级别的时间戳 */ public static function getMillisecond() { //获取毫秒的时间戳 $time = explode ( " ", microtime () ); $time = $time[1] . ($time[0] * 1000); $time2 = explode( ".", $time ); $time = $time2[0]; return $time; } /** * 输出xml字符 * @throws WxPayException **/ public function ToXml() { if(!is_array($this->values) || count($this->values) <= 0) { throw new WxPayException("数组数据异常!"); } $xml = ""; foreach ($this->values as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val.""; }else{ $xml.="<".$key.">"; } } $xml.=""; return $xml; } /** * 格式化参数格式化成url参数 */ public function ToUrlParams() { $buff = ""; foreach ($this->values as $k => $v) { if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /** * 以post方式提交xml到对应的接口url * * @param string $xml 需要post的xml数据 * @param string $url url * @param bool $useCert 是否需要证书,默认不需要 * @param int $second url执行超时时间,默认30s * @throws WxPayException */ public static function postXmlCurl($xml, $url, $useCert = false, $second = 30,$path=null) { $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,TRUE); // curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验 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 == true){ //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); if($path) curl_setopt($ch,CURLOPT_SSLCERT, $path.'apiclient_cert.pem'); else curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH); curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); if($path) curl_setopt($ch,CURLOPT_SSLKEY, $path.'apiclient_key.pem'); else curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH); } //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); curl_close($ch); throw new WxPayException("curl出错,错误码:$error"); } } /** * * 上报数据, 上报的时候将屏蔽所有异常流程 * @param string $usrl * @param int $startTimeStamp * @param array $data */ public static function reportCostTime($url, $startTimeStamp, $data) { //如果不需要上报数据 if(WxPayConfig::REPORT_LEVENL == 0){ return; } //如果仅失败上报 if(WxPayConfig::REPORT_LEVENL == 1 && array_key_exists("return_code", $data) && $data["return_code"] == "SUCCESS" && array_key_exists("result_code", $data) && $data["result_code"] == "SUCCESS") { return; } //上报逻辑 $endTimeStamp = self::getMillisecond(); $objInput = new WxPayReport(); $objInput->SetInterface_url($url); $objInput->SetExecute_time_($endTimeStamp - $startTimeStamp); //返回状态码 if(array_key_exists("return_code", $data)){ $objInput->SetReturn_code($data["return_code"]); } //返回信息 if(array_key_exists("return_msg", $data)){ $objInput->SetReturn_msg($data["return_msg"]); } //业务结果 if(array_key_exists("result_code", $data)){ $objInput->SetResult_code($data["result_code"]); } //错误代码 if(array_key_exists("err_code", $data)){ $objInput->SetErr_code($data["err_code"]); } //错误代码描述 if(array_key_exists("err_code_des", $data)){ $objInput->SetErr_code_des($data["err_code_des"]); } //商户订单号 if(array_key_exists("out_trade_no", $data)){ $objInput->SetOut_trade_no($data["out_trade_no"]); } //设备号 if(array_key_exists("device_info", $data)){ $objInput->SetDevice_info($data["device_info"]); } try{ self::report($objInput); } catch (WxPayException $e){ //不做任何处理 } } public function xmltoarray($xml) { //禁止引用外部xml实体 libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring),true); return $val; } }