微信支付啊,一向以官方文档太烂而著称,怎么说呢,服务器端的demo基本都没有实例,而且重名参数比较多,服务器端开发与app端开发一个参数用错就要找好长时间。支付宝支付开发了很多种类,遇到的问题能很快解决,微信的就呵呵了。
最近看他的退款接口要用证书,而文档中证书怎么使用完全没写。查了很多资料啊
至于如何下载和生成,在商户号里面 api安全 里面设置,也不一一赘述。
生成后的证书解压后如下三个文件,上传服务器自己选定位置,后台退款接口需要用到
iis安装过程可以参考下面两篇文章
https://blog.csdn.net/yangzhiman/article/details/78997152
https://blog.csdn.net/Sunny_Ran/article/details/77991201
已经很详尽了,我这里就不多写了。
主要介绍代码中使用证书的方法
先定义好几个函数,模型类请用自己的喔,或者直接写原生的查询数据库方法,改动也很简单,以下PayConfig数据库中存储支付配置信息,因为我这边是多应用支付模块
PayOrder为数据库中订单的数据表
这两个都根据自己的实际情况改变
/**
* 设置支付参数
* @param $id
* @return bool
*/
public function setConfig($id){
//查找数据
$config = PayConfig::where('id',$id)->first();
if(!$config->id){
return false;
}
/*配置参数*/
$this->config = [
'appid' => $config->appid, /*微信开放平台上的应用id*/
'mch_id' => $config->mch_id, /*微信申请成功之后邮件中的商户id*/
'api_key' => $config->publickey, /*在微信商户平台上自己设定的api密钥 32位*/
'notify_url' => '回调地址,退款接口不用设置'
];
$this->recher =0;
return $config;
}
//获取指定长度的随机字符串
public function getRandChar($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
public function arrayToXml($arr)
{
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val))
{
$xml.="<".$key.">".$val."</".$key.">";
}
else
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
$xml.="</xml>";
return $xml;
}
/**
* curl方法
* @param $xml
* @param $url
* @param int $second
* @param int $cert
* @return bool|false|string
*/
public function postXmlCurl($xml,$url,$second=30, $cert=0)
{
//初始化curl
$ch = curl_init();
//超时时间
curl_setopt($ch,CURLOPT_TIMEOUT,$second);
curl_setopt($ch,CURLOPT_URL, $url);
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);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//设置证书
if($cert){
//此处证书引用绝对路径
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
curl_setopt($ch, CURLOPT_SSLCERT, 'D:\项目名\public\certNotify\apiclient_cert.pem');
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
curl_setopt($ch, CURLOPT_SSLKEY, 'D:\项目名\public\certNotify\apiclient_key.pem');
}
//运行curl
$data = curl_exec($ch);
//返回结果
if($data)
{
curl_close($ch);
return $data;
}
else
{
$error = curl_errno($ch);
//echo "curl出错,错误码:$error"."<br>";
return json_encode(array('code'=>$error,'status'=>0));
//return false;
}
}
/**
*xml转成数组
*/
public function xmlstr_to_array($xmlstr) {
//将XML转为array
return json_decode(json_encode(simplexml_load_string($xmlstr, 'SimpleXMLElement',LIBXML_NOCDATA)), true);
}
/**
* 退款方法
* @param $id 为数据库中订单id,供查询订单使用
* @return bool
*/
public function refundOrder($id){
$order = PayOrder::where('id',$id)->first();
if(!$order) return false;
//设置微信配置参数
$config = $this->setConfig($order->config_id);
//微信退款接口地址
$url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
$this->recher = $onoce_str = $this->getRandChar(32);//随机字符串
$data["appid"] = $this->config['appid'];//你得APPID
$data["mch_id"] = $this->config['mch_id'];//商户号
$data["nonce_str"] = $onoce_str;
$data["out_refund_no"] = $order->out_trade_no;//你得订单号
$data["out_trade_no"] = $order->out_trade_no;//你得订单号
$data["transaction_id"] = $order->trade_no;//订单支付成功后微信返回的微信数据中订单号,传了订单号可不传这个参数
$total_fee = $order->total_amount;//你得订单号
$data["refund_fee"] = $total_fee*100;//支付金额
$data["total_fee"] = $total_fee*100;//支付金额
$data["sign"] = $this->getSign($data, false);
$xml = $this->arrayToXml($data);
$response = $this->postXmlCurl($xml, $url ,30 ,1 );
//laravel 的日志打印
Log::useFiles(storage_path('logs/wxpayapi.log'), 'debug');
Log::debug($response);
//将微信返回的结果xml转成数组
$result = $this->xmlstr_to_array($response);
//laravel 的日志打印
Log::debug($result);
if($result['result_code'] && $result['result_code']=='SUCCESS'){
//更新数据
$order->status = 4;
$order->save();
$status = true;
}else{
//laravel 的日志打印
Log::useFiles(storage_path('logs/wxpayapi.log'), 'debug');
Log::debug($result);
$status = false;
}
return $status;
}
调用方法
$this->refundOrder('传入你数据库中的退款订单id');
以上要改动的就是postXmlCurl 中你下载的证书在你服务器的绝对位置。
安装教程也一定要仔细走一遍喔
不然报错400 No required SSL certificate was sent