微信支付
//微信支付接口
public function wx_pay($pay_sn,$openid,$goods_amount){
//$pay_sn 订单号
//$goods_amount 总价格
// $APPID = 'wx4cbf015baaaaaaa'; //appid
// $APPSECRET = 'a4fa4a7d2711043bbbbbbbbb'; //appsecret
// $MCH_ID = '155304111111';
// $KEY = 'Ailangshangmaoyouxiangon11111234';
//获取微信配置信息
$wxconfig = db('wxconfig')->find();
// echo '<pre/>';print_r($wxconfig);die;
$APPID = $wxconfig['xcx_appid']; //小程序appid
$APPSECRET = $wxconfig['xcx_appsecret']; //小程序appsecret
$MCH_ID = $wxconfig['xcx_mch_id']; //商户号
$KEY = $wxconfig['xcx_key']; //微信支付KEY
// $APPID = config(''); //appid
// $APPSECRET = config(''); //appsecret
// $MCH_ID = config(''); //商户号
$notify_url = 'https://'.$_SERVER['HTTP_HOST'].'/index.php/home/buy/notify'; //支付完成回调地址url,不能带参数
$trade_type = 'JSAPI';//交易类型 默认JSAPI
$out_trade_no = $pay_sn; //商户订单号
// $nonce_str = mt_rand(10000, 99999).time();//随机字符串
$nonce_str = $this->getNonceStr();//随机字符串
$time_start = date("YmdHis"); //开始时间
$time_expire = date("YmdHis", time() + 600); //结束时间
$Total_fee = $goods_amount*100; //总金额
$body = 'testbody';
$spbill_create_ip = $_SERVER['SERVER_ADDR']; //终端IP
//这里是按照顺序的 因为下面的签名是按照(字典序)顺序 排序错误 肯定出错
$post['appid'] = $APPID;
$post['body'] = $body;
$post['mch_id'] = $MCH_ID;
$post['nonce_str'] = $nonce_str;//随机字符串
$post['notify_url'] = $notify_url;
$post['openid'] = $openid;
$post['out_trade_no'] = $out_trade_no;
$post['spbill_create_ip'] = $spbill_create_ip;//服务器终端的ip
$post['total_fee'] = intval($Total_fee); //总金额 最低为一分钱 必须是整数
$post['trade_type'] = 'JSAPI';
$sign = $this->MakeSign($post, $KEY); //签名
//echo '<pre/>';print_r($post);
$post_xml = '<xml>
<appid>'.$APPID.'</appid>
<body>'.$body.'</body>
<mch_id>'.$MCH_ID.'</mch_id>
<nonce_str>'.$nonce_str.'</nonce_str>
<notify_url>'.$notify_url.'</notify_url>
<openid>'.$openid.'</openid>
<out_trade_no>'.$out_trade_no.'</out_trade_no>
<sign>'.$sign.'</sign>
<spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
<total_fee>'.$Total_fee.'</total_fee>
<trade_type>'.$trade_type.'</trade_type>
</xml>';
// echo '<pre/>';print_r($post_xml);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$xml = $this->send_prePaycurl($url,$post_xml);
//将【统一下单】api返回xml数据转换成数组,全要大写
// $array = $this->xml2array($xml);
$array = $this->_xmldataparse($xml);
// echo '<pre/>';print_r($array);die;
if($array['return_code'] == 'SUCCESS' || $array['result_code'] == 'SUCCESS'){
$time = time();
//二次签名数组
$tmp = array();
$tmp['appId'] = $APPID;
$tmp['timeStamp'] = strval($time);
$tmp['nonceStr'] = $nonce_str;
$tmp['signType'] = 'MD5';
$tmp['package'] = 'prepay_id='.$array['prepay_id'];
//返回数据数组
$data['code'] = 1;
$data['timeStamp'] = strval($time);
$data['nonceStr'] = $nonce_str;
$data['signType'] = 'MD5';
$data['package'] = 'prepay_id='.$array['prepay_id'];
$data['paySign'] = $this->MakeSign($tmp,$KEY);
$data['pay_sn'] = $out_trade_no;
}else{
$data['code'] = 0;
$data['msg'] = '错误';
$data['return_code'] = $array['return_code'];
$data['return_msg'] = $array['return_msg'];
$data['err_code_des'] = $array['err_code_des'];
}
// echo 123456789;
// echo '<pre/>';print_r($array);die;
return $data;
}
/** * 将参数拼接为url: key=value&key=value * @param $params * @return string */
private function ToUrlParams($params){
$string = '';
if(!empty($params)){
// $array = array();
// foreach($params as $key =>$value){
// $array[] = $key.'='.$value;
// }
// $string = implode('&',$array);
$array = '';
foreach ($params as $key => $value) {
$array .= !$array ? $key . '=' . $value : '&' . $key . '=' . $value;
}
$string = $array;
}
// echo '<pre/>';print_r($array);die;
return $string;
}
//生成随机字符串
public static function getNonceStr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return strtoupper($str);
}
/** * 调用接口, $data是数组参数 * @return 签名 */
private function send_prePaycurl($url,$xmlData) {
// $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
$header[] = "Content-type: text/xml";
$curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlData);
$data = curl_exec($curl);
if (curl_errno($curl)) {
print curl_error($curl);
}
curl_close($curl);
return $data;
}
//xml数据解析函数
private function _xmldataparse($data){
$msg = array();
$msg = (array)simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
return $msg;
}
//支付完成回调地址url
public function notify_url(){
$post = file_get_contents("php://input");
// echo '<pre/>';print_r($post);die;
//创建存入access_token的文件
$accessfile = __DIR__.'/aaa.txt';
$file = fopen($accessfile,'a');
$file = json_decode(file_get_contents($accessfile),true);
$fd = fopen($accessfile,'w');
$data = simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);//XML转数组
$data = json_encode($data);
$data = json_decode($data,true);
// if ($result['result_code'] == 'SUCCESS' && $result['return_code'] == 'SUCCESS') {
if($data['return_code']=='SUCCESS' && $data['result_code'] == 'SUCCESS'){
//订单号
$out_trade_no = $data['out_trade_no'];
//修改成已支付
$upd['order_state'] = 20;
$upd['transaction_id'] = $data['transaction_id'];
$upd['pay_time'] = time();
$update = db('order')->where('pay_sn='.$out_trade_no)->update($upd);
//更新积分
$total_fee = $data['total_fee']/100;
fwrite($fd,$post);
fclose($fd);
if($total_fee >=1 ){
db('member')->where('openid like "%'.$data['openid'].'%" ')->setInc('member_points',$total_fee);
}
echo 'SUCCESS';
}else{
echo 'FAIL';
}
}
微信退款
//测试退款
public function aaa(){
$out_trade_no = '19120210485069094001';
$order_amount= '0.01';
$this->refund($out_trade_no,$order_amount);
}
//退款
public function refund($out_trade_no,$order_amount){
//获取微信配置信息
$wxconfig = db('wxconfig')->find();
$APPID = $wxconfig['xcx_appid']; //小程序appid
// $APPSECRET = $wxconfig['xcx_appsecret']; //小程序appsecret
$MCH_ID = $wxconfig['xcx_mch_id']; //商户号
$KEY = $wxconfig['xcx_key']; //微信支付KEY
$nonce_str = $this->getNonceStr();//随机字符串
$out_trade_no = $out_trade_no; //商户订单号
$out_refund_no = rand(100000,999999).time(); //退单号
$a = db('order')->where('pay_sn='.$out_trade_no)->find();
$total_fee = $a['order_amount']*100; //订单金额
$refund_fee = $order_amount*100; //退单金额
$transaction_id = $a['transaction_id'];
if($refund_fee<1){
return json_encode(['code'=>400,'msg'=>'退款金额不得小于1分']);
}
if($refund_fee>$total_fee){
return json_encode(['code'=>400,'msg'=>'退款金额不得大于订单总金额']);
}
//这里是按照顺序的 因为下面的签名是按照(字典序)顺序 排序错误 肯定出错
$post['appid'] = $APPID;
$post['mch_id'] = $MCH_ID;
$post['nonce_str'] = $nonce_str;//随机字符串
$post['out_refund_no'] = $out_refund_no;
//$post['out_trade_no'] = $out_trade_no;
$post['refund_fee'] = intval($refund_fee); //退款总金额 最低为一分钱 必须是整数
$post['total_fee'] = intval($total_fee); //总金额 最低为一分钱 必须是整数
$post['transaction_id'] = $transaction_id; //微信单号
$sign = $this->MakeSign($post, $KEY); //签名
$post['sign'] = $sign;
//echo '<pre/>';print_r($post_xml);die;
$post_xml = '<xml>
<appid>'.$APPID.'</appid>
<mch_id>'.$MCH_ID.'</mch_id>
<nonce_str>'.$nonce_str.'</nonce_str>
<out_refund_no>'.$out_refund_no.'</out_refund_no>
<refund_fee>'.$refund_fee.'</refund_fee>
<total_fee>'.$total_fee.'</total_fee>
<transaction_id>'.$transaction_id.'</transaction_id>
<sign>'.$sign.'</sign>
</xml>';
// <out_trade_no>'.$out_trade_no.'</out_trade_no>
// echo $KEY;
$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
$xml = $this->postXmlCurl($url,$post_xml);
//将退款api返回xml数据转换成数组,全要大写
$array = $this->_xmldataparse($xml);
echo '<pre/>';print_r($array);die;
if(($array['return_code']=='SUCCESS') && ($array['result_code']=='SUCCESS')){
$arrays['refund_state'] = 2;
db('order')->where('pay_sn='.$out_trade_no)->update($arrays);
return json_encode(['code'=>200,'msg'=>'退款成功']);
}else{
return json_encode(['code'=>400,'msg'=>'退款失败']);
}
}
public function postXmlCurl($url,$xml)
{
$ch = curl_init();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
// curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
// return CURLOPT_RETURNTRANSFER;
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);//严格校验
// $header[] = "Content-type: text/xml";
//设置header
curl_setopt($ch, CURLOPT_HEADER, false);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//使用证书:cert 与 key 分别属于两个.pem文件
//第一种
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, '/www/wwwroot/hzp/extend/Wxpay/cert/apiclient_cert.pem');
// curl_setopt($ch, CURLOPT_SSLCERT, 'https://hzp.bjcaicheng.cn/extend/Wxpay/cert/apiclient_cert.pem');
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
// curl_setopt($ch, CURLOPT_SSLKEY, 'https://hzp.bjcaicheng.cn/extend/Wxpay/cert/apiclient_key.pem');
curl_setopt($ch, CURLOPT_SSLKEY, '/www/wwwroot/hzp/extend/Wxpay/cert/apiclient_key.pem');
//第二种
// curl_setopt($ch, CURLOPT_CAINFO, dirname(dirname(__FILE__))."/cert".DIRECTORY_SEPARATOR.'rootca.pem');
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
// var_dump($data);die;
// echo '<pre/>';print_r($data);die;
//返回结果
if($data){
// return 333;
curl_close($ch);
return $data;
} else {
// return 222;
$error = curl_errno($ch);
// return $error;
curl_close($ch);
// return false;
return json_encode("curl出错,错误码:$error");
}
}