├── log ├── access_token.sample.json └── jsapi_ticket.sample.json ├── .gitignore ├── lib ├── SDKRuntimeException.php ├── Log.php ├── WxpayServerPub.php ├── WxpayClientPub.php ├── UnifiedOrderPub.php ├── JsSdk.php └── CommonUtilPub.php ├── LICENSE ├── conf └── WxPay.pub.config.sample.php ├── callback └── notifyUrl.php ├── README.md └── index.php /log/access_token.sample.json: -------------------------------------------------------------------------------- 1 | {"access_token":"","expire_time":0} 2 | -------------------------------------------------------------------------------- /log/jsapi_ticket.sample.json: -------------------------------------------------------------------------------- 1 | {"jsapi_ticket":"","expire_time":0} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | master.sh 4 | conf/WxPay.pub.config.php 5 | log/* 6 | -------------------------------------------------------------------------------- /lib/SDKRuntimeException.php: -------------------------------------------------------------------------------- 1 | getMessage(); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /lib/Log.php: -------------------------------------------------------------------------------- 1 | data = $this->xmlToArray($xml); 17 | } 18 | 19 | function checkSign() 20 | { 21 | $tmpData = $this->data; 22 | unset($tmpData['sign']); 23 | $sign = $this->getSign($tmpData);//本地签名 24 | if ($this->data['sign'] == $sign) { 25 | return TRUE; 26 | } 27 | return FALSE; 28 | } 29 | 30 | /** 31 | * 获取微信的请求数据 32 | */ 33 | function getData() 34 | { 35 | return $this->data; 36 | } 37 | 38 | /** 39 | * 设置返回微信的xml数据 40 | */ 41 | function setReturnParameter($parameter, $parameterValue) 42 | { 43 | $this->returnParameters[$this->trimString($parameter)] = $this->trimString($parameterValue); 44 | } 45 | 46 | /** 47 | * 生成接口参数xml 48 | */ 49 | function createXml() 50 | { 51 | return $this->arrayToXml($this->returnParameters); 52 | } 53 | 54 | /** 55 | * 将xml数据返回微信 56 | */ 57 | function returnXml() 58 | { 59 | $returnXml = $this->createXml(); 60 | return $returnXml; 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /conf/WxPay.pub.config.sample.php: -------------------------------------------------------------------------------- 1 | 38 | 39 | -------------------------------------------------------------------------------- /lib/WxpayClientPub.php: -------------------------------------------------------------------------------- 1 | parameters[$this->trimString($parameter)] = $this->trimString($parameterValue); 20 | } 21 | 22 | /** 23 | * 作用:设置标配的请求参数,生成签名,生成接口参数xml 24 | */ 25 | function createXml() 26 | { 27 | $this->parameters["appid"] = WxPayConfPub::APPID;//公众账号ID 28 | $this->parameters["mch_id"] = WxPayConfPub::MCHID;//商户号 29 | $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串 30 | $this->parameters["sign"] = $this->getSign($this->parameters);//签名 31 | return $this->arrayToXml($this->parameters); 32 | } 33 | 34 | /** 35 | * 作用:post请求xml 36 | */ 37 | function postXml() 38 | { 39 | $xml = $this->createXml(); 40 | $this->response = $this->postXmlCurl($xml,$this->url,$this->curl_timeout); 41 | return $this->response; 42 | } 43 | 44 | /** 45 | * 作用:使用证书post请求xml 46 | */ 47 | function postXmlSSL() 48 | { 49 | $xml = $this->createXml(); 50 | $this->response = $this->postXmlSSLCurl($xml,$this->url,$this->curl_timeout); 51 | return $this->response; 52 | } 53 | 54 | /** 55 | * 作用:获取结果,默认不使用证书 56 | */ 57 | function getResult() 58 | { 59 | $this->postXml(); 60 | $this->result = $this->xmlToArray($this->response); 61 | return $this->result; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /callback/notifyUrl.php: -------------------------------------------------------------------------------- 1 | saveData($xml); 22 | 23 | //验证签名,并回应微信。 24 | //对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败, 25 | //微信会通过一定的策略(如30分钟共8次)定期重新发起通知, 26 | //尽可能提高通知的成功率,但微信不保证通知最终能成功。 27 | if($notify->checkSign() == FALSE){ 28 | $notify->setReturnParameter("return_code","FAIL");//返回状态码 29 | $notify->setReturnParameter("return_msg","签名失败");//返回信息 30 | }else{ 31 | $notify->setReturnParameter("return_code","SUCCESS");//设置返回码 32 | } 33 | $returnXml = $notify->returnXml(); 34 | echo $returnXml; 35 | 36 | //==商户根据实际情况设置相应的处理流程,此处仅作举例======= 37 | 38 | //以log文件形式记录回调信息 39 | $log = new Log(); 40 | $logName="../log/notify_url.log";//log文件路径 41 | $log->log_result($logName,"【接收到的notify通知】:\n".$xml."\n"); 42 | 43 | if($notify->checkSign() == TRUE) 44 | { 45 | if ($notify->data["return_code"] == "FAIL") { 46 | //此处应该更新一下订单状态,商户自行增删操作 47 | $log->log_result($logName,"【通信出错】:\n".$xml."\n"); 48 | } 49 | elseif($notify->data["result_code"] == "FAIL"){ 50 | //此处应该更新一下订单状态,商户自行增删操作 51 | $log->log_result($logName,"【业务出错】:\n".$xml."\n"); 52 | } 53 | else{ 54 | //此处应该更新一下订单状态,商户自行增删操作 55 | $log->log_result($logName,"【支付成功】:\n".$xml."\n"); 56 | } 57 | 58 | //商户自行增加处理流程, 59 | //例如:更新订单状态 60 | //例如:数据库操作 61 | //例如:推送支付完成信息 62 | } 63 | ?> 64 | 65 | -------------------------------------------------------------------------------- /lib/UnifiedOrderPub.php: -------------------------------------------------------------------------------- 1 | url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; 12 | //设置curl超时时间 13 | $this->curl_timeout = WxPayConfPub::CURL_TIMEOUT; 14 | } 15 | 16 | /** 17 | * 生成接口参数xml 18 | */ 19 | function createXml() 20 | { 21 | try 22 | { 23 | //检测必填参数 24 | if($this->parameters["out_trade_no"] == null) 25 | { 26 | throw new SDKRuntimeException("缺少统一支付接口必填参数out_trade_no!"."
"); 27 | }elseif($this->parameters["body"] == null){ 28 | throw new SDKRuntimeException("缺少统一支付接口必填参数body!"."
"); 29 | }elseif ($this->parameters["total_fee"] == null ) { 30 | throw new SDKRuntimeException("缺少统一支付接口必填参数total_fee!"."
"); 31 | }elseif ($this->parameters["notify_url"] == null) { 32 | throw new SDKRuntimeException("缺少统一支付接口必填参数notify_url!"."
"); 33 | }elseif ($this->parameters["trade_type"] == null) { 34 | throw new SDKRuntimeException("缺少统一支付接口必填参数trade_type!"."
"); 35 | }elseif ($this->parameters["trade_type"] == "JSAPI" && 36 | $this->parameters["openid"] == NULL){ 37 | throw new SDKRuntimeException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!"."
"); 38 | } 39 | $this->parameters["appid"] = WxPayConfPub::APPID;//公众账号ID 40 | $this->parameters["mch_id"] = WxPayConfPub::MCHID;//商户号 41 | $this->parameters["spbill_create_ip"] = $_SERVER['REMOTE_ADDR'];//终端ip 42 | if (!isset($this->parameters["nonce_str"])) { 43 | $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串 44 | } 45 | $this->parameters["sign"] = $this->getSign($this->parameters);//签名 46 | return $this->arrayToXml($this->parameters); 47 | }catch (SDKRuntimeException $e) 48 | { 49 | die($e->errorMessage()); 50 | } 51 | } 52 | 53 | /** 54 | * 获取prepay_id 55 | */ 56 | function getPrepayId() 57 | { 58 | $this->postXml(); 59 | $this->result = $this->xmlToArray($this->response); 60 | $prepay_id = $this->result["prepay_id"]; 61 | return $prepay_id; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wxpay-php 2 | ========= 3 | 4 | php项目基于微信支付JS SDK和JS API的接入开发 5 | 6 | 因为php框架繁多,而且项目开发进度比较赶,线上代码迁移出来的时间也有限,此处的代码没有经过备案域名和线上服务器测试,肯定会有很多问题,所以样例代码仅供参考 7 | 8 | --- 9 | 10 | ### 前言 11 | 12 | 因为抢红包风波,微信封杀了支付宝链接,不得不紧急加入微信支付。 13 | 14 | 微信支付的开发文档太坑,不才已被虐哭,趁现在还在坑里,记录一下留个纪念。 15 | 16 | ### 开发相关资料(排名不分先后) 17 | 18 | * [微信商户服务中心](https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/faq2_tmpl) 19 | 20 | * [商户平台开发者文档1](http://pay.weixin.qq.com/wiki/doc/api/index.html) 21 | 22 | * [商户平台开发者文档2](http://pay.weixin.qq.com/wiki/doc/api/jsapi.php) 23 | 24 | * [商户平台开发者文档3](http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=1_1) 25 | 26 | * [微信JS-SDK说明文档](http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html) 27 | 28 | * [支付开发教程(微信商户平台版)](https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl) 29 | 30 | * [代公众号使用JS SDK说明](https://open.weixin.qq.com/cgi-bin/showdocument?action=doc&id=open1421823488&t=0.37369911512359977) 31 | 32 | * [JSSDK demo页面](http://demo.open.weixin.qq.com/jssdk/) 33 | 34 | * [JSSDK demo示例代码下载](http://demo.open.weixin.qq.com/jssdk/sample.zip) 35 | 36 | ### 注意点 37 | 38 | * 微信5.0后的版本才支持微信支付 39 | 40 | * 微信支付的jssdk接口只能在微信客户端里面才有效果,普通浏览器无法测试 41 | 42 | * 微信支付的相关代码必须部署在线上,域名必须备案,而且域名必须跟 <微信公众平台> 里相关设置里的域名一致 43 | 44 | * 微信大小写非常敏感,timestamp和timeStamp以及appId和appid不要弄错,要在对的接口使用对的大小写,里面是混着用的 45 | 46 | * 商户号和微信商户号要区分出来,也就是MCHID,开通微信支付后有一封邮件,里面会有相关的信息,登陆商户后台也能找到 47 | 48 | * 只有服务号才能接入微信支付,不同的服务号之前可以跨号支付,订阅号里面不能调用微信支付,会报“不允许跨号支付”的错误 49 | 50 | ### 关于签名 51 | 52 | 我开发的时候遇到三次签名生成: 53 | 54 | 1. wx.config 里面有一次 signature 的签名生成,调用的是官方sdk的方法,它用的是 SHA1 加密,生成之后的签名没有转大写 55 | 56 | 2. 获取prepay\_id的时候,中间会生成一次签名,调用的是官方sdk的方法,它用的是 MD5 加密,生成之后的签名统一转成大写 57 | 58 | 3. wx.chooseWXPay 里面有最后一次 paySign 的签名生成,我调用了步骤2里面的那个接口,最后测试成功了 59 | 60 | ### 分享代码 61 | 62 | 因为目前用的项目的框架是比较奇葩的,我之前已经把官方的代码临时整合并修改成适合项目的代码,不能直接用了,后面的日子将逐步等工作闲暇的时候,整理出直接能用的来分享给还没入坑有需要的童鞋们。 63 | 64 | --- 65 | 66 | ## 代码相关 67 | 68 | ### 开发环境 69 | 70 | 本地相关开发环境如下: 71 | 72 | * 编辑器: MacVim 73 | 74 | * php: 5.5.13,接入微信支付的相关扩展都装了,主要应该是curl扩展 75 | 76 | * nginx: 1.4.2 77 | 78 | * 操作系统: Yosemite 10.0.2 79 | 80 | ### 创建相关文件 81 | 82 | WxPay.pub.config.sample.php => WxPay.pub.config.php // 配置文件 83 | access_token.sample.json => access_token.json // 临时存储access_token 84 | jsapi_ticket.sample.json => jsapi_ticket.json // 临时存储jsapi_ticket 85 | 86 | ### 代码文件结构 87 | 88 | . 89 | ├── LICENSE 90 | ├── README.md -------------------------说明文档 91 | ├── callback --------------------------回调 92 | │   └── notifyUrl.php -----------------回调接口文件 93 | ├── conf ------------------------------配置 94 | │   ├── WxPay.pub.config.php ----------配置文件 95 | │   └── WxPay.pub.config.sample.php ---配置文件样本 96 | ├── index.php -------------------------主入口文件 97 | ├── lib -------------------------------类库 98 | │   ├── CommonUtilPub.php -------------所有接口的基类 99 | │   ├── JsSdk.php ---------------------微信支付新推出的js sdk 100 | │   ├── Log.php -----------------------日志类库 101 | │   ├── SDKRuntimeException.php -------异常类库 102 | │   ├── UnifiedOrderPub.php -----------统一支付接口类 103 | │   ├── WxpayClientPub.php ------------请求型接口的基类 104 | │   └── WxpayServerPub.php ------------响应型接口的基类 105 | ├── log -------------------------------日志 106 | │   ├── access_token.json -------------access_token临时存储文件 107 | │   ├── access_token.sample.json ------access_token临时存储文件样本 108 | │   ├── jsapi_ticket.json -------------jsapi_ticket临时存储文件 109 | │   ├── jsapi_ticket.sample.json ------jsapi_ticket临时存储文件样本 110 | │   └── notify_url.log ----------------回调接口日志文件 111 | └── master.sh -------------------------git提交shell懒人脚本 112 | 113 | 4 directories, 19 files 114 | -------------------------------------------------------------------------------- /lib/JsSdk.php: -------------------------------------------------------------------------------- 1 | appId = $appId; 13 | $this->appSecret = $appSecret; 14 | } 15 | 16 | public function getSignPackage() { 17 | $jsapiTicket = $this->getJsApiTicket(); 18 | 19 | // 注意 URL 一定要动态获取,不能 hardcode. 20 | $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; 21 | $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; 22 | 23 | $timestamp = time(); 24 | $nonceStr = $this->createNonceStr(); 25 | 26 | // 这里参数的顺序要按照 key 值 ASCII 码升序排序 27 | $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; 28 | 29 | $signature = sha1($string); 30 | 31 | $signPackage = array( 32 | "appId" => $this->appId, 33 | "nonceStr" => $nonceStr, 34 | "timestamp" => $timestamp, 35 | "url" => $url, 36 | "signature" => $signature, 37 | "rawString" => $string 38 | ); 39 | return $signPackage; 40 | } 41 | 42 | private function createNonceStr($length = 16) { 43 | $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 44 | $str = ""; 45 | for ($i = 0; $i < $length; $i++) { 46 | $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); 47 | } 48 | return $str; 49 | } 50 | 51 | private function getJsApiTicket() { 52 | // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例 53 | $data = json_decode(file_get_contents("log/jsapi_ticket.json")); 54 | if ($data->expire_time < time()) { 55 | $accessToken = $this->getAccessToken(); 56 | // 如果是企业号用以下 URL 获取 ticket 57 | // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken"; 58 | $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken"; 59 | $res = json_decode($this->httpGet($url)); 60 | $ticket = $res->ticket; 61 | if ($ticket) { 62 | $data->expire_time = time() + 7000; 63 | $data->jsapi_ticket = $ticket; 64 | $fp = fopen("log/jsapi_ticket.json", "w"); 65 | fwrite($fp, json_encode($data)); 66 | fclose($fp); 67 | } 68 | } else { 69 | $ticket = $data->jsapi_ticket; 70 | } 71 | 72 | return $ticket; 73 | } 74 | 75 | private function getAccessToken() { 76 | // access_token 应该全局存储与更新,以下代码以写入到文件中做示例 77 | $data = json_decode(file_get_contents("log/access_token.json")); 78 | if ($data->expire_time < time()) { 79 | // 如果是企业号用以下URL获取access_token 80 | // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret"; 81 | $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret"; 82 | $res = json_decode($this->httpGet($url)); 83 | $access_token = $res->access_token; 84 | if ($access_token) { 85 | $data->expire_time = time() + 7000; 86 | $data->access_token = $access_token; 87 | $fp = fopen("log/access_token.json", "w"); 88 | fwrite($fp, json_encode($data)); 89 | fclose($fp); 90 | } 91 | } else { 92 | $access_token = $data->access_token; 93 | } 94 | return $access_token; 95 | } 96 | 97 | private function httpGet($url) { 98 | $curl = curl_init(); 99 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 100 | curl_setopt($curl, CURLOPT_TIMEOUT, 500); 101 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 102 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); 103 | curl_setopt($curl, CURLOPT_URL, $url); 104 | 105 | $res = curl_exec($curl); 106 | curl_close($curl); 107 | 108 | return $res; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | GetSignPackage(); 18 | $timeStamp = $signPackage['timestamp']; 19 | $nonceStr = $signPackage['nonceStr']; 20 | 21 | 22 | // 获取prepay_id 23 | // 具体参数设置可以看文档http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1 24 | $unifiedOrder = new UnifiedOrderPub(); 25 | $unifiedOrder->setParameter("openid",$openId);//用户openId 26 | $unifiedOrder->setParameter("body", "贡献一分钱");//商品描述,文档里写着不能超过32个字符,否则会报错,经过实际测试,临界点大概在128左右,稳妥点最好按照文档,不要超过32个字符 27 | $unifiedOrder->setParameter("out_trade_no", "123456");//商户订单号 28 | $unifiedOrder->setParameter("total_fee", "1");//总金额,单位为分 29 | $unifiedOrder->setParameter("notify_url",WxPayConfPub::NOTIFY_URL);//通知地址 30 | $unifiedOrder->setParameter("trade_type","JSAPI");//交易类型 31 | $unifiedOrder->setParameter("nonce_str", $nonceStr);//随机字符串 32 | //非必填参数,商户可根据实际情况选填 33 | //$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号 34 | //$unifiedOrder->setParameter("device_info","XXXX");//设备号 35 | //$unifiedOrder->setParameter("attach","XXXX");//附加数据 36 | //$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间 37 | //$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 38 | //$unifiedOrder->setParameter("goods_tag","XXXX");//商品标记 39 | //$unifiedOrder->setParameter("openid","XXXX");//用户标识 40 | //$unifiedOrder->setParameter("product_id","XXXX");//商品ID 41 | $prepayId = $unifiedOrder->getPrepayId(); 42 | 43 | // 计算paySign 44 | $payPackage = [ 45 | "appId" => WxPayConfPub::APPID, 46 | "nonceStr" => $nonceStr, 47 | "package" => "prepay_id=" . $prepayId, 48 | "signType" => "MD5", 49 | "timeStamp" => $timeStamp 50 | ]; 51 | $paySign = $unifiedOrder->getSign($payPackage); 52 | $payPackage['paySign'] = $paySign; 53 | 54 | ?> 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 微信支付接入 64 | 65 | 66 | 67 |
68 | 69 | 发起一个微信支付请求 70 | 71 |
72 | 73 | 74 | 75 | 109 | 110 | -------------------------------------------------------------------------------- /lib/CommonUtilPub.php: -------------------------------------------------------------------------------- 1 | $v) 46 | { 47 | if($urlencode) 48 | { 49 | $v = urlencode($v); 50 | } 51 | //$buff .= strtolower($k) . "=" . $v . "&"; 52 | $buff .= $k . "=" . $v . "&"; 53 | } 54 | $reqPar; 55 | if (strlen($buff) > 0) 56 | { 57 | $reqPar = substr($buff, 0, strlen($buff)-1); 58 | } 59 | return $reqPar; 60 | } 61 | 62 | /** 63 | * 作用:生成签名 64 | */ 65 | public function getSign($Obj) 66 | { 67 | foreach ($Obj as $k => $v) 68 | { 69 | $Parameters[$k] = $v; 70 | } 71 | //签名步骤一:按字典序排序参数 72 | ksort($Parameters); 73 | $String = $this->formatBizQueryParaMap($Parameters, false); 74 | //echo '【string1】'.$String.'
'; 75 | //签名步骤二:在string后加入KEY 76 | $String = $String."&key=".WxPayConfPub::KEY; 77 | //echo "【string2】".$String."
"; 78 | //签名步骤三:MD5加密 79 | $String = md5($String); 80 | //echo "【string3】 ".$String."
"; 81 | //签名步骤四:所有字符转为大写 82 | $result_ = strtoupper($String); 83 | //echo "【result】 ".$result_."
"; 84 | return $result_; 85 | } 86 | 87 | /** 88 | * 作用:array转xml 89 | */ 90 | function arrayToXml($arr) 91 | { 92 | $xml = ""; 93 | foreach ($arr as $key=>$val) 94 | { 95 | if (is_numeric($val)) 96 | { 97 | $xml.="<".$key.">".$val.""; 98 | 99 | } 100 | else 101 | $xml.="<".$key.">"; 102 | } 103 | $xml.=""; 104 | return $xml; 105 | } 106 | 107 | /** 108 | * 作用:将xml转为array 109 | */ 110 | public function xmlToArray($xml) 111 | { 112 | //将XML转为array 113 | $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); 114 | return $array_data; 115 | } 116 | 117 | /** 118 | * 作用:以post方式提交xml到对应的接口url 119 | */ 120 | public function postXmlCurl($xml,$url,$second=30) 121 | { 122 | //初始化curl 123 | $ch = curl_init(); 124 | //设置超时 125 | curl_setopt($ch, CURLOPT_TIMEOUT, $second); 126 | //这里设置代理,如果有的话 127 | //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8'); 128 | //curl_setopt($ch,CURLOPT_PROXYPORT, 8080); 129 | curl_setopt($ch,CURLOPT_URL, $url); 130 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); 131 | curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); 132 | //设置header 133 | curl_setopt($ch, CURLOPT_HEADER, FALSE); 134 | //要求结果为字符串且输出到屏幕上 135 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 136 | //post提交方式 137 | curl_setopt($ch, CURLOPT_POST, TRUE); 138 | curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 139 | //运行curl 140 | $data = curl_exec($ch); 141 | //返回结果 142 | if($data) 143 | { 144 | curl_close($ch); 145 | return $data; 146 | } 147 | else 148 | { 149 | $error = curl_errno($ch); 150 | echo "curl出错,错误码:$error"."
"; 151 | echo "错误原因查询
"; 152 | curl_close($ch); 153 | return false; 154 | } 155 | } 156 | 157 | /** 158 | * 作用:使用证书,以post方式提交xml到对应的接口url 159 | */ 160 | function postXmlSSLCurl($xml,$url,$second=30) 161 | { 162 | $ch = curl_init(); 163 | //超时时间 164 | curl_setopt($ch,CURLOPT_TIMEOUT,$second); 165 | //这里设置代理,如果有的话 166 | //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8'); 167 | //curl_setopt($ch,CURLOPT_PROXYPORT, 8080); 168 | curl_setopt($ch,CURLOPT_URL, $url); 169 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); 170 | curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); 171 | //设置header 172 | curl_setopt($ch,CURLOPT_HEADER,FALSE); 173 | //要求结果为字符串且输出到屏幕上 174 | curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE); 175 | //设置证书 176 | //使用证书:cert 与 key 分别属于两个.pem文件 177 | //默认格式为PEM,可以注释 178 | curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); 179 | curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfPub::SSLCERT_PATH); 180 | //默认格式为PEM,可以注释 181 | curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); 182 | curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfPub::SSLKEY_PATH); 183 | //post提交方式 184 | curl_setopt($ch,CURLOPT_POST, true); 185 | curl_setopt($ch,CURLOPT_POSTFIELDS,$xml); 186 | $data = curl_exec($ch); 187 | //返回结果 188 | if($data){ 189 | curl_close($ch); 190 | return $data; 191 | } 192 | else { 193 | $error = curl_errno($ch); 194 | echo "curl出错,错误码:$error"."
"; 195 | echo "错误原因查询
"; 196 | curl_close($ch); 197 | return false; 198 | } 199 | } 200 | 201 | /** 202 | * 作用:打印数组 203 | */ 204 | function printErr($wording='',$err='') 205 | { 206 | print_r('
');
207 | 		echo $wording."
"; 208 | var_dump($err); 209 | print_r('
'); 210 | } 211 | } 212 | --------------------------------------------------------------------------------