小程序的退款流程都比较清晰,如果做过支付的,上手比较容易,支付在此就不多说,现在说一下在退款流程中遇到的坑
证书保存路径问题,按网上流程,把证书保存在根目录的cert中,在curl中获取,都显示58错误,找不到证书,后来经过研究,把证书放在了程序文件夹public中,新建cert保存,就可以正常访问
//使用的啊里云宝塔,存放证书路径,放在public中,新建cert $cert = '/cert/cdzw_apiclient_cert.pem'; $key = '/cert/cdzw_apiclient_key.pem'; //默认格式为PEM,可以注释,使用getcwd()方法,拼接证书的绝对路径 curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLCERT,getcwd().$cert); //默认格式为PEM,可以注释,使用getcwd()方法,拼接证书的绝对路径 curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); curl_setopt($ch, CURLOPT_SSLKEY,getcwd().$key);
详细代码如下
//网页端向微信平台提交退款申请
public function submitDrawBack(){
//通过订单ID,获取订单信息
$id = $this->request->param('id');
$data = CdzwOrderModel::where('id',$id)->find();
//通过微信api进行退款流程
$nonce_str = $this->nonce_str();//随机32位字符串
$out_refund_no = $this->getOrderNum();//随机不重复退款单号
$total_fee = $data['total'] * 100;//总金额,单位:分
$refund_fee = $data['recTotal'] * 100;//退款金额,单位:分
$appid = constant("APPID");//小程序appid
$mch_id = constant("MCHID");//小程序商户号
$parma = array(
'appid'=> $appid,
'mch_id'=> $mch_id,
'nonce_str'=> $nonce_str,
'out_trade_no'=> $data['trade_no'],//小程序自定义订单号,支付时后台生成
'out_refund_no'=> $out_refund_no,
'refund_fee'=> $refund_fee,
'total_fee'=> $total_fee,
'transaction_id' => $data['pay_no'],//小程序平台订单号,微信平台生成
);
$KEY = constant("KEY");//小程序支付秘钥
$parma['sign'] = $this->MakeSign($parma, $KEY);//签名
$post_xml = $this->arrayToXml($parma);//把参数转化成xml格式
//向微信平台api发送退款参数
$xmlresult = $this->postXmlSSLCurl($post_xml,'https://api.mch.weixin.qq.com/secapi/pay/refund');
//解析返回的参数
$array = $this->xml2array($xmlresult);
//两个success表示退款成功,无需使用回调,在此进行逻辑处理即可
if ($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS') {
CdzwOrderModel::where('id',$id)->update(['status'=>7,'dbCompleteTime'=>date("Y-m-d H:i")]);
$status = 1;
$message = '退款成功';
}else{
$status = 0;
$message = '退款失败';
}
return ['status' => $status, 'message' => $message];
// return $array;
}
//数组转字符串方法
protected 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;
}
//获取xml里面数据,转换成array
private function xml2array($xml)
{
$p = xml_parser_create();
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = [];
foreach ($index as $key => $value) {
if ($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}
//需要使用证书的请求
function postXmlSSLCurl($xml,$url,$second=30)
{
//使用的啊里云宝塔,存放证书路径,放在public中,新建cert
$cert = '/cert/cdzw_apiclient_cert.pem';
$key = '/cert/cdzw_apiclient_key.pem';
$ch = curl_init();
//超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
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);
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释,使用getcwd()方法,拼接证书的绝对路径
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT,getcwd().$cert);
//默认格式为PEM,可以注释,使用getcwd()方法,拼接证书的绝对路径
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY,getcwd().$key);
//post提交方式
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$data = curl_exec($ch);
// p($data);die;
//返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
echo "curl出错,错误码:$error" . "<br>";
curl_close($ch);
return false;
}
}
636

被折叠的 条评论
为什么被折叠?



