php微信支付之APP支付方法.docx
《php微信支付之APP支付方法.docx》由会员分享,可在线阅读,更多相关《php微信支付之APP支付方法.docx(6页珍藏版)》请在冰豆网上搜索。
php微信支付之APP支付方法
WechatAppPay文件代码如下:
复制代码代码如下:
php
namespacecommon\services\WechatPay;
classWechatAppPayextendsWechatPayBase
{
//package参数
public$package=[];
//异步通知参数
public$notify=[];
//推送预支付订单参数
protected$config=[];
//存储accesstoken和获取时间的文件
protected$file;
//accesstoken
protected$accessToken;
//取accesstoken的url
constACCESS_TOKEN_URL='
//生成预支付订单提交地址
constPOST_ORDER_URL='
publicfunction__construct()
{
$this->file=__DIR__.'/payAccessToken.txt';
}
/**
*创建APP支付最终返回参数
*@throws\Exception
*@returnmultitype:
stringNULL
*/
publicfunctioncreateAppPayData()
{
$this->generateConfig();
$prepayid=$this->getPrepayid();
try{
$array=[
'appid'=>$this->appid,
'appkey'=>$this->paySignkey,
'noncestr'=>$this->getRandomStr(),
'package'=>'Sign=WXPay',
'partnerid'=>$this->partnerId,
'prepayid'=>$prepayid,
'timestamp'=>(string)time(),
];
$array['sign']=$this->sha1Sign($array);
unset($array['appkey']);
}catch(\Exception$e){
thrownew\Exception($e->getMessage());
}
return$array;
}
/**
*验证支付成功后的通知参数
*
*@throws\Exception
*@returnboolean
*/
publicfunctionverifyNotify()
{
try{
$staySignStr=$this->notify;
unset($staySignStr['sign']);
$sign=$this->signData($staySignStr);
return$this->notify['sign']===$sign;
}catch(\Exception$e){
thrownew\Exception($e->getMessage());
}
}
/**
*魔术方法,给添加支付参数进来
*
*@paramstring$name 参数名
*@paramstring$value 参数值
*/
publicfunction__set($name,$value)
{
$this->$name=$value;
}
/**
*设置accesstoken
*@paramstring$token
*@throws\Exception
*@returnboolean
*/
publicfunctionsetAccessToken()
{
try{
if(!
file_exists($this->file)||!
is_file($this->file)){
$f=fopen($this->file,'a');
fclose($f);
}
$content=file_get_contents($this->file);
if(!
empty($content)){
$info=$content,true);
if(time()-$info['getTime']<7150){
$this->accessToken=$info['accessToken'];
returntrue;
}
}
//文件内容为空或accesstoken已失效,重新获取
$this->outputAccessTokenToFile();
}catch(\Exception$e){
thrownew\Exception($e->getMessage());
}
returntrue;
}
/**
*写入accesstoken到文件
*@throws\Exception
*@returnboolean
*/
protectedfunctionoutputAccessTokenToFile()
{
try{
$f=fopen($this->file,'wb');
$token=[
'accessToken'=>$this->getAccessToken(),
'getTime'=>time(),
];
flock($f,LOCK_EX);
fwrite($f,$token));
flock($f,LOCK_UN);
fclose($f);
$this->accessToken=$token['accessToken'];
}catch(\Exception$e){
thrownew\Exception($e->getMessage());
}
returntrue;
}
/**
*取accesstoken
*
*@throws\Exception
*@returnstring
*/
protectedfunctiongetAccessToken()
{
$url=sprintf(self:
:
ACCESS_TOKEN_URL,$this->appid,$this->appSecret);
$result=$this->getUrl($url),true);
if(isset($result['errcode'])){
thrownew\Exception("getaccesstokenfailed:
{$result['errmsg']}");
}
return$result['access_token'];
}
/**
*取预支付会话标识
*
*@throws\Exception
*@returnstring
*/
protectedfunctiongetPrepayid()
{
$data=$this->config);
$url=sprintf(self:
:
POST_ORDER_URL,$this->accessToken);
$result=$this->postUrl($url,$data),true);
if(isset($result['errcode'])&&$result['errcode']!
=0){
thrownew\Exception($result['errmsg']);
}
if(!
isset($result['prepayid'])){
thrownew\Exception('getprepayidfailed,urlrequesterror.');
}
return$result['prepayid'];
}
/**
*组装预支付参数
*
*@throws\Exception
*/
protectedfunctiongenerateConfig()
{
try{
$this->config=[
'appid'=>$this->appid,
'traceid'=>$this->traceid,
'noncestr'=>$this->getRandomStr(),
'timestamp'=>time(),
'package'=>$this->generatePackage(),
'sign_method'=>$this->sign_method,
];
$this->config['app_signature']=$this->generateSign();
}catch(\Exception$e){
thrownew\Exception($e->getMessage());
}
}
/**
*生成package字段
*
*生成规则:
*1、生成sign的值signValue
*2、对package参数再次拼接成查询字符串,值需要进行urlencode
*3、将sign=signValue拼接到2生成的字符串后面得到最终的package字符串
*
*第2步urlencode空格需要编码成%20而不是+
*
*RFC1738会把空格编码成+
*RFC3986会把空格编码成%20
*
*@returnstring
*/
protectedfunctiongeneratePackage()
{
$this->package['sign']=$this->signData($this->package);
returnhttp_build_query($this->package,'','&',PHP_QUERY_RFC3986);
}
/**
*生成签名
*
*@returnstring
*/
protectedfunctiongenerateSign()
{
$signArray=[
'appid'=>$this->appid,
'appkey'=>$this->paySignkey,
'noncestr'=>$this->config['noncestr'],
'package'=>$this->config['package'],
'timestamp'=>$this->config['timestamp'],
'traceid'=>$this->traceid,
];
return$this->sha1Sign($signArray);
}
/**
*签名数据
*
*生成规则:
*1、字典排序,拼接成查询字符串格式,不需要urlencode
*2、上一步得到的字符串最后拼接上key=paternerKey
*3、MD5哈希字符串并转换成大写得到sign的值signValue
*
*@paramarray$data待签名数据
*@returnstring最终签名结果
*/
protectedfunctionsignData($data)
{
ksort($data);
$str=$this->arrayToString($data);
$str.="&key={$this->partnerKey}";
returnstrtoupper($this->signMd5($str));
}
/**
*sha1签名
*签名规则
*1、字典排序
*2、拼接查询字符串
*3、sha1运算
*
*@paramarray$arr
*@returnstring
*/
protectedfunctionsha1Sign($arr)
{
ksort($arr);
returnsha1($this->arrayToString($arr));
}
}