PHP 微信支付类 demo
一切尽在代码中,代码附有注释,欢迎大家参考。
<?php classWxpayService { protected$mchid; protected$appid; protected$key; publicfunction__construct($mchid,$appid,$key) { $this->mchid=$mchid;//微信支付商户号PartnerID通过微信支付商户资料审核后邮件发送 $this->appid=$appid;//公众号APPID通过微信支付商户资料审核后邮件发送 $this->key=$key;//https://pay.weixin.qq.com帐户设置-安全设置-API安全-API密钥-设置API密钥 } /** *@paramstring$openid调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid *@paramfloat$totalFee收款总费用单位元 *@paramstring$outTradeNo唯一的订单号 *@paramstring$orderName订单名称 *@paramstring$notifyUrl支付结果通知url不要有问号 *https://mp.weixin.qq.com/微信支付-开发配置-测试目录 *测试目录http://mp.izhanlue.com/paytest/最后需要斜线,(需要精确到二级或三级目录) *@returnstring */ publicfunctioncreateJsBizPackage($openid,$totalFee,$outTradeNo,$orderName,$notifyUrl,$timestamp) { $config=array( 'mch_id'=>$this->mchid, 'appid'=>$this->appid, 'key'=>$this->key, ); $unified=array( 'appid'=>$config['appid'], 'attach'=>'支付',//商家数据包,原样返回 'body'=>$orderName, 'mch_id'=>$config['mch_id'], 'nonce_str'=>self::createNonceStr(), 'notify_url'=>$notifyUrl, 'openid'=>$openid,//rade_type=JSAPI,此参数必传 'out_trade_no'=>$outTradeNo, 'spbill_create_ip'=>'127.0.0.1', 'total_fee'=>intval($totalFee*100),//单位转为分 'trade_type'=>'JSAPI', ); $unified['sign']=self::getSign($unified,$config['key']); $responseXml=self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder',self::arrayToXml($unified)); /* <xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> <appid><![CDATA[wx00e5904efec77699]]></appid> <mch_id><![CDATA[1220647301]]></mch_id> <nonce_str><![CDATA[1LHBROsdmqfXoWQR]]></nonce_str> <sign><![CDATA[ACA7BC8A9164D1FBED06C7DFC13EC839]]></sign> <result_code><![CDATA[SUCCESS]]></result_code> <prepay_id><![CDATA[wx2015032016590503f1bcd9c30421762652]]></prepay_id> <trade_type><![CDATA[JSAPI]]></trade_type> </xml> */ $unifiedOrder=simplexml_load_string($responseXml,'SimpleXMLElement',LIBXML_NOCDATA); if($unifiedOrder===false){ die('parsexmlerror'); } if($unifiedOrder->return_code!='SUCCESS'){ die($unifiedOrder->return_msg); } if($unifiedOrder->result_code!='SUCCESS'){ die($unifiedOrder->err_code); /* NOAUTH商户无此接口权限 NOTENOUGH余额不足 ORDERPAID商户订单已支付 ORDERCLOSED订单已关闭 SYSTEMERROR系统错误 APPID_NOT_EXISTAPPID不存在 MCHID_NOT_EXISTMCHID不存在 APPID_MCHID_NOT_MATCHappid和mch_id不匹配 LACK_PARAMS缺少参数 OUT_TRADE_NO_USED商户订单号重复 SIGNERROR签名错误 XML_FORMAT_ERRORXML格式错误 REQUIRE_POST_METHOD请使用post方法 POST_DATA_EMPTYpost数据为空 NOT_UTF8编码格式错误 */ } //$unifiedOrder->trade_type交易类型调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP //$unifiedOrder->prepay_id预支付交易会话标识微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时 //$unifiedOrder->code_url二维码链接trade_type为NATIVE是有返回,可将该参数值生成二维码展示出来进行扫码支付 $arr=array( "appId"=>$config['appid'], "timeStamp"=>$timestamp, "nonceStr"=>self::createNonceStr(), "package"=>"prepay_id=".$unifiedOrder->prepay_id, "signType"=>'MD5', ); $arr['paySign']=self::getSign($arr,$config['key']); return$arr; } publicfunctionnotify() { $config=array( 'mch_id'=>$this->mchid, 'appid'=>$this->appid, 'key'=>$this->key, ); $postStr=$GLOBALS["HTTP_RAW_POST_DATA"]; //error_log($postStr,3,'./str.txt'); /* $postStr='<xml> <appid><![CDATA[wx00e5904efec77699]]></appid> <attach><![CDATA[支付测试]]></attach> <bank_type><![CDATA[CMB_CREDIT]]></bank_type> <cash_fee><![CDATA[1]]></cash_fee> <fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[Y]]></is_subscribe> <mch_id><![CDATA[1220647301]]></mch_id> <nonce_str><![CDATA[a0tZ41phiHm8zfmO]]></nonce_str> <openid><![CDATA[oU3OCt5O46PumN7IE87WcoYZY9r0]]></openid> <out_trade_no><![CDATA[550bf2990c51f]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code> <sign><![CDATA[F6F519B4DD8DB978040F8C866C1E6250]]></sign> <time_end><![CDATA[20150320181606]]></time_end> <total_fee>1</total_fee> <trade_type><![CDATA[JSAPI]]></trade_type> <transaction_id><![CDATA[1008840847201503200034663980]]></transaction_id> </xml>'; */ $postObj=simplexml_load_string($postStr,'SimpleXMLElement',LIBXML_NOCDATA); if($postObj===false){ die('parsexmlerror'); } if($postObj->return_code!='SUCCESS'){ die($postObj->return_msg); } if($postObj->result_code!='SUCCESS'){ die($postObj->err_code); } $arr=(array)$postObj; unset($arr['sign']); if(self::getSign($arr,$config['key'])==$postObj->sign){ //$mch_id=$postObj->mch_id;//微信支付分配的商户号 //$appid=$postObj->appid;//微信分配的公众账号ID //$openid=$postObj->openid;//用户在商户appid下的唯一标识 //$transaction_id=$postObj->transaction_id;//微信支付订单号 //$out_trade_no=$postObj->out_trade_no;//商户订单号 //$total_fee=$postObj->total_fee;//订单总金额,单位为分 //$is_subscribe=$postObj->is_subscribe;//用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效 //$attach=$postObj->attach;//商家数据包,原样返回 //$time_end=$postObj->time_end;//支付完成时间 echo'<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; return$postObj; } } /** *curlget * *@paramstring$url *@paramarray$options *@returnmixed */ publicstaticfunctioncurlGet($url='',$options=array()) { $ch=curl_init($url); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($ch,CURLOPT_TIMEOUT,30); if(!empty($options)){ curl_setopt_array($ch,$options); } //https请求不验证证书和host curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); $data=curl_exec($ch); curl_close($ch); return$data; } publicstaticfunctioncurlPost($url='',$postData='',$options=array()) { 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); $data=curl_exec($ch); curl_close($ch); return$data; } publicstaticfunctioncreateNonceStr($length=16) { $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $str=''; for($i=0;$i<$length;$i++){ $str.=substr($chars,mt_rand(0,strlen($chars)-1),1); } return$str; } publicstaticfunctionarrayToXml($arr) { $xml="<xml>"; foreach($arras$key=>$val){ if(is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } $xml.="</xml>"; return$xml; } /** *例如: *appid:wxd930ea5d5a258f4f *mch_id:10000100 *device_info:1000 *Body:test *nonce_str:ibuaiVcKdpRxkhJA *第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下: *stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_i *d=10000100&nonce_str=ibuaiVcKdpRxkhJA"; *第二步:拼接支付密钥: *stringSignTemp="stringA&key=192006250b4c09247ec02edce69f6a2d" *sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" */ publicstaticfunctiongetSign($params,$key) { ksort($params,SORT_STRING); $unSignParaString=self::formatQueryParaMap($params,false); $signStr=strtoupper(md5($unSignParaString."&key=".$key)); return$signStr; } protectedstaticfunctionformatQueryParaMap($paraMap,$urlEncode=false) { $buff=""; ksort($paraMap); foreach($paraMapas$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; } }
以上代码大家都能看得懂吧,有哪里不明白的地方欢迎给我留言,我会在第一时间和大家取得联系的。谢谢大家对毛票票网站的支持。