PHP实现 APP端微信支付功能
前面已经写了手机APP支付宝支付,今天再把手机APP微信支付补上,前期的准备工作在这里就不多说了,可以参考微信支付开发文档,一定要仔细阅读开发文档,可以让你少踩点坑;准备工作完成后就是配置参数,调用统一下单接口,支付后异步回调三部曲啦;
1.我封装好的一个支付类文件,多余的东西都去除掉了,并且把配置参数放到了这个支付类中,只需要修改Weixinpayandroid方法内的几个参数就可以直接复制使用:
classWxpayandroid
{
//参数配置
public$config=array(
'appid'=>"",/*微信开放平台上的应用id*/
'mch_id'=>"",/*微信申请成功之后邮件中的商户id*/
'api_key'=>"",/*在微信商户平台上自己设定的api密钥32位*/
);
//服务器异步通知页面路径(必填)
public$notify_url='';
//商户订单号(必填,商户网站订单系统中唯一订单号)
public$out_trade_no='';
//商品描述(必填,不填则为商品名称)
public$body='';
//付款金额(必填)
public$total_fee=0;
//自定义超时(选填,支持dhmc)
public$time_expire='';
private$WxPayHelper;
publicfunctionWeixinpayandroid($total_fee,$tade_no)
{
$this->total_fee=intval($total_fee*100);//订单的金额1元
$this->out_trade_no=$tade_no;//date('YmdHis').substr(time(),-5).substr(microtime(),2,5).sprintf('%02d',rand(0,99));//订单号
$this->body='wxpay';//支付描述信息
$this->time_expire=date('YmdHis',time()+86400);//订单支付的过期时间(eg:一天过期)
$this->notify_url="http://www.ceshi.com/notifyandroid";//异步通知URL(更改支付状态)
//数据以JSON的形式返回给APP
$app_response=$this->doPay();
if(isset($app_response['return_code'])&&$app_response['return_code']=='FAIL'){
$errorCode=100;
$errorMsg=$app_response['return_msg'];
$this->echoResult($errorCode,$errorMsg);
}else{
$errorCode=0;
$errorMsg='success';
$responseData=array(
'notify_url'=>$this->notify_url,
'app_response'=>$app_response,
);
$this->echoResult($errorCode,$errorMsg,$responseData);
}
}
//接口输出
functionechoResult($errorCode=0,$errorMsg='success',$responseData=array())
{
$arr=array(
'errorCode'=>$errorCode,
'errorMsg'=>$errorMsg,
'responseData'=>$responseData,
);
exit(json_encode($arr));//exit可以正常发送给APPjson数据
//returnjson_encode($arr);//在TP5中return这个json数据,APP接收到的是null,无法正常吊起微信支付
}
functiongetVerifySign($data,$key)
{
$String=$this->formatParameters($data,false);
//签名步骤二:在string后加入KEY
$String=$String."&key=".$key;
//签名步骤三:MD5加密
$String=md5($String);
//签名步骤四:所有字符转为大写
$result=strtoupper($String);
return$result;
}
functionformatParameters($paraMap,$urlencode)
{
$buff="";
ksort($paraMap);
foreach($paraMapas$k=>$v){
if($k=="sign"){
continue;
}
if($urlencode){
$v=urlencode($v);
}
$buff.=$k."=".$v."&";
}
$reqPar;
if(strlen($buff)>0){
$reqPar=substr($buff,0,strlen($buff)-1);
}
return$reqPar;
}
/**
*得到签名
*@paramobject$obj
*@paramstring$api_key
*@returnstring
*/
functiongetSign($obj,$api_key)
{
foreach($objas$k=>$v)
{
$Parameters[strtolower($k)]=$v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String=$this->formatBizQueryParaMap($Parameters,false);
//签名步骤二:在string后加入KEY
$String=$String."&key=".$api_key;
//签名步骤三:MD5加密
$result=strtoupper(md5($String));
return$result;
}
/**
*获取指定长度的随机字符串
*@paramint$length
*@returnAmbigous
*/
functiongetRandChar($length){
$str=null;
$strPol="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max=strlen($strPol)-1;
for($i=0;$i<$length;$i++){
$str.=$strPol[rand(0,$max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
}
return$str;
}
/**
*数组转xml
*@paramarray$arr
*@returnstring
*/
functionarrayToXml($arr)
{
$xml="";
foreach($arras$key=>$val)
{
if(is_numeric($val))
{
$xml.="<".$key.">".$val."".$key.">";
}
else
$xml.="<".$key.">".$key.">";
}
$xml.=" ";
return$xml;
}
/**
*以post方式提交xml到对应的接口url
*
*@paramstring$xml需要post的xml数据
*@paramstring$urlurl
*@parambool$useCert是否需要证书,默认不需要
*@paramint$secondurl执行超时时间,默认30s
*@throwsWxPayException
*/
functionpostXmlCurl($xml,$url,$second=30,$useCert=false,$sslcert_path='',$sslkey_path='')
{
$ch=curl_init();
//设置超时
curl_setopt($ch,CURLOPT_TIMEOUT,$second);
curl_setopt($ch,CURLOPT_URL,$url);
//设置header
curl_setopt($ch,CURLOPT_HEADER,FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
if($useCert==true){
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
//设置证书
//使用证书:cert与key分别属于两个.pem文件
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT,$sslcert_path);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY,$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);
returnfalse;
}
}
/**
*获取当前服务器的IP
*@returnAmbigous
*/
functionget_client_ip()
{
if(isset($_SERVER['REMOTE_ADDR'])){
$cip=$_SERVER['REMOTE_ADDR'];
}elseif(getenv("REMOTE_ADDR")){
$cip=getenv("REMOTE_ADDR");
}elseif(getenv("HTTP_CLIENT_IP")){
$cip=getenv("HTTP_CLIENT_IP");
}else{
$cip="127.0.0.1";
}
return$cip;
}
/**
*将数组转成uri字符串
*@paramarray$paraMap
*@parambool$urlencode
*@returnstring
*/
functionformatBizQueryParaMap($paraMap,$urlencode)
{
$buff="";
ksort($paraMap);
foreach($paraMapas$k=>$v)
{
if($urlencode)
{
$v=urlencode($v);
}
$buff.=strtolower($k)."=".$v."&";
}
$reqPar;
if(strlen($buff)>0)
{
$reqPar=substr($buff,0,strlen($buff)-1);
}
return$reqPar;
}
/**
*XML转数组
*@paramunknown$xml
*@returnmixed
*/
functionxmlToArray($xml)
{
//将XML转为array
$array_data=json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true);
return$array_data;
}
publicfunctionchkParam()
{
//用户网站订单号
if(empty($this->out_trade_no)){
die('out_trade_noerror');
}
//商品描述
if(empty($this->body)){
die('bodyerror');
}
if(empty($this->time_expire)){
die('time_expireerror');
}
//检测支付金额
if(empty($this->total_fee)||!is_numeric($this->total_fee)){
die('total_feeerror');
}
//异步通知URL
if(empty($this->notify_url)){
die('notify_urlerror');
}
if(!preg_match("#^http:\/\/#i",$this->notify_url)){
$this->notify_url="http://".$_SERVER['HTTP_HOST'].$this->notify_url;
}
returntrue;
}
/**
*生成支付(返回给APP)
*@returnboolean|mixed
*/
publicfunctiondoPay(){
//检测构造参数
$this->chkParam();
return$this->createAppPara();
}
/**
*APP统一下单
*/
privatefunctioncreateAppPara()
{
$url="https://api.mch.weixin.qq.com/pay/unifiedorder";
$data["appid"]=$this->config['appid'];//微信开放平台审核通过的应用APPID
$data["body"]=$this->body;//商品或支付单简要描述
$data["mch_id"]=$this->config['mch_id'];//商户号
$data["nonce_str"]=$this->getRandChar(32);//随机字符串
$data["notify_url"]=$this->notify_url;//通知地址
$data["out_trade_no"]=$this->out_trade_no;//商户订单号
$data["spbill_create_ip"]=$this->get_client_ip();//终端IP
$data["total_fee"]=$this->total_fee;//总金额
$data["time_expire"]=$this->time_expire;//交易结束时间
$data["trade_type"]="APP";//交易类型
$data["sign"]=$this->getSign($data,$this->config['api_key']);//签名
$xml=$this->arrayToXml($data);
$response=$this->postXmlCurl($xml,$url);
//将微信返回的结果xml转成数组
$responseArr=$this->xmlToArray($response);
if(isset($responseArr["return_code"])&&$responseArr["return_code"]=='SUCCESS'){
return$this->getOrder($responseArr['prepay_id']);
}
return$responseArr;
}
/**
*执行第二次签名,才能返回给客户端使用
*@paramint$prepayId:预支付交易会话标识
*@returnarray
*/
publicfunctiongetOrder($prepayId)
{
$data["appid"]=$this->config['appid'];
$data["noncestr"]=$this->getRandChar(32);
$data["package"]="Sign=WXPay";
$data["partnerid"]=$this->config['mch_id'];
$data["prepayid"]=$prepayId;
$data["timestamp"]=time();
$data["sign"]=$this->getSign($data,$this->config['api_key']);
$data["packagestr"]="Sign=WXPay";
return$data;
}
/**
*异步通知信息验证
*@returnboolean|mixed
*/
publicfunctionverifyNotify()
{
$xml=isset($GLOBALS['HTTP_RAW_POST_DATA'])?$GLOBALS['HTTP_RAW_POST_DATA']:'';
if(!$xml){
returnfalse;
}
$wx_back=$this->xmlToArray($xml);
if(empty($wx_back)){
returnfalse;
}
$checkSign=$this->getVerifySign($wx_back,$this->config['api_key']);
if($checkSign=$wx_back['sign']){
return$wx_back;
}else{
returnfalse;
}
}
}
2.创建控制器定义统一下单接口和支付后的异步回调接口:
//异步通知接口
publicfunctionnotifyandroid()
{
$wxpayandroid=new\Wxpayandroid;//实例化微信支付类
$verify_result=$wxpayandroid->verifyNotify();
if($verify_result['return_code']=='SUCCESS'&&$verify_result['result_code']=='SUCCESS'){
//商户订单号
$out_trade_no=$verify_result['out_trade_no'];
//交易号
$trade_no=$verify_result['transaction_id'];
//交易状态
$trade_status=$verify_result['result_code'];
//支付金额
$total_fee=$verify_result['total_fee']/100;
//支付过期时间
$pay_date=$verify_result['time_end'];
$order=newOrder();
$ret=$order->getOrderN2($out_trade_no);//获取订单信息
$total_amount=$ret['money'];
if($total_amount==$total_fee){
//验证成功修改数据库的订单状态等$result['out_trade_no']为订单号
//此处写自己的逻辑代码
}
exit(' ');
}else{
exit(' ');
}
}
//调用统一下单接口生成预支付订单并把数据返回给APP
publicfunctionwxpayandroid(Request$request)
{
$param=$request->param();//接收值
$tade_no=$param['orderCode'];
$order=newOrder();//实例化订单
$ret=$order->getOrderN2($tade_no);//查询订单信息
$total_fee=$ret['money'];//订单总金额
$wxpayandroid=new\Wxpayandroid;//实例化微信支付类
$res=$wxpayandroid->Weixinpayandroid($total_fee,$tade_no);//调用weixinpay方法
}
封装一个支付类文件,并把配置参数放到支付类内,再定义控制器创建两个方法,这样两步就可以把手机APP微信支付搞定啦。
总结
以上所述是小编给大家介绍的PHP实现APP端微信支付功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。