基于thinkphp5框架

微信小程序或微信支付相关操作

目录

支付

退款

订单查询

退款查询

支付成功,进行回调

退款成功 进行回调

用到的方法


支付

/*** 预支付请求接口(POST)* @param string $openid openid* @param string $body 商品简单描述* @param string $order_sn 订单编号* @param string $total_fee 金额* @return  json的数据*/public function prepay(){tp_log('预支付请求数据===>' . json_encode($_POST), 'prepay', request()->controller());$goods_user = db('tf_goods_user')->where(array('order_no' => $_POST['order_no']))->find();$goods = db('tf_goods')->where(array('id' => $goods_user['goods_id']))->find();//判断产品的数量if (($goods['sales_initial'] - $goods['sales_actual']) <= 0) {$return['status'] = 0;$return['info'] = '此产品已售完';exit(json_encode($return));}$order_no = $_POST['order_no']; //订单号$is_sale = $_POST['is_sale'];$openid = $_POST['openid'];$goods_name = $_POST['goods_name'];$pay_price = $_POST['price'];$attach['is_sale'] = $_POST['is_sale'];$attach['sale_id'] = $_POST['sale_id'];$nonce_str = $this->nonce_str();//随机字符串$order_no_ssh = $this->get_orderssh(); //商户订单号
//注意 订单号为自己创建的订单 和支付没有任何关系 商户订单号是支付单号 用来支付的 每当订单号发起支付 就会有新的商户订单号 商户订单号是不重复的  发起一次支付就要生成新的商户订单号 要保存下来 订单表要有对应的支付订单表 而订单号与商户订单号是一对多的关系 订单表最终保存的商户订单号是支付成功的那个 也可以 没调起支付就根据订单号去修改订单表的商户订单号 只有商户订单号才能发起退款 相当于商户订单号统计记录到订单表里面 退款查询等操作  商户订单号  其实订单生成就不会改数据了 也可以用订单号改为商户订单号 这样支付 取消 在支付 也可以的(out_trade_no)//组装支付数据$data = ['appid' => config('pay.APPID'),'mch_id' => config('pay.MCHID'),'nonce_str' => $nonce_str,'body' => $goods_name,  //商品名称组合'attach' => json_encode($attach),'out_trade_no' => $order_no_ssh,//$order_no,        //订单号 商户订单号'total_fee' => intval($pay_price * 100),'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],'notify_url' => config('pay.NOTIFY_URL'),'trade_type' => 'JSAPI','openid' => $openid];//订单支付表创建订单支付数据$p_o_data['createtime'] = time();$p_o_data['order_no'] = $order_no;$p_o_data['order_no_ssh'] = $order_no_ssh;$p_o_data['ready'] = json_encode($data);$p_o_return = db('tf_pay_order')->insert($p_o_data);if(!$p_o_return){//失败$return['status'] = -1;$return['info'] = $p_o_data;exit(json_encode($return));}// 获取签名$sign = $this->makeSign($data);$data['sign'] = $sign;$xml = $this->toXml($data);$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; //发起支付接口链接//发起预支付请求$prepay_return_reslut_xml = $this->http_request($url, $xml);$xml_to_arr = $this->fromXml($prepay_return_reslut_xml);$return_result = json_encode($xml_to_arr, true);tp_log('预支付请求返回数据array===>' .$return_result , 'prepay', request()->controller());//记录预支付返回信息db('tf_goods_order')->where(array('order_no' => $order_no))->update(array('go_pay' => $return_result,'updatetime' => time(),'updateuser' => $openid));if($xml_to_arr['return_code'] == 'SUCCESS' && $xml_to_arr['result_code'] == 'SUCCESS'){//成功$time = time();//临时数组用于签名$tmp = ['appId' => config('pay.APPID'),'nonceStr' => $nonce_str,'package' => 'prepay_id='.$xml_to_arr['prepay_id'],'signType' => 'MD5','timeStamp' => "$time",];$data['timeStamp'] = "$time";//时间戳$data['nonceStr'] = $nonce_str;//随机字符串$data['signType'] = 'MD5';//签名算法,暂支持 MD5$data['package'] = 'prepay_id='.$xml_to_arr['prepay_id'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*$data['paySign'] = $this->makeSign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;$data['out_trade_no'] = $out_trade_no;$return['status'] = 1;$return['info'] = $data;}else{//失败$return['status'] = -1;$return['info'] = $xml_to_arr;}exit(json_encode($return));}//curl请求public function http_request($url, $data = null, $headers = array()){$curl = curl_init();if (count($headers) >= 1) {curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);}curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);if (!empty($data)) {curl_setopt($curl, CURLOPT_POST, 1);curl_setopt($curl, CURLOPT_POSTFIELDS, $data);}curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);$output = curl_exec($curl);curl_close($curl);return $output;}

退款

/*** 申请退款API* @param $transaction_id* @param  double $total_fee 账单总金额* @param  double $refund_fee 退款金额* @return bool* @throws BaseException*/public function refund(){$transaction_id = '4200000712202007274705432240';$total_fee = '0.01';$refund_fee = '0.01';// 当前时间$time = time();// 生成随机字符串$nonceStr = md5($time . $transaction_id . $total_fee . $refund_fee);// API参数$params = ['appid' => config('pay.APPID'),'mch_id' => config('pay.MCHID'),'nonce_str' => $nonceStr,'transaction_id' => $transaction_id,'out_refund_no' => $time,'total_fee' => $total_fee * 100,'refund_fee' => $refund_fee * 100,'notify_url' => config('pay.NOTIFY_URL_REFUND'),//退款回调地址];// 生成签名$params['sign'] = $this->makeSign($params);tp_log('退款请求数据===>' . json_encode($params), 'refund', request()->controller());// 请求API$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';$result = $this->post($url, $this->toXml($params), true, $this->getCertPem());$prepay = $this->fromXml($result);// 请求失败if (empty($result)) {throw new BaseException(['msg' => '微信退款api请求失败']);}// 格式化返回结果$prepay = $this->fromXml($result);tp_log('退款返回数据===>' . json_encode($prepay), 'refund', request()->controller());// 请求失败
//        if ($prepay['return_code'] === 'FAIL') {
//            throw new BaseException(['msg' => 'return_msg: ' . $prepay['return_msg']]);
//        }
//        if ($prepay['result_code'] === 'FAIL') {
//            throw new BaseException(['msg' => 'err_code_des: ' . $prepay['err_code_des']]);
//        }return true;}/*** 模拟POST请求* @param $url* @param array $data* @param bool $useCert* @param array $sslCert* @return mixed*/public function post($url, $data = [], $useCert = false, $sslCert = []){$header = ['Content-type: application/json;'];$curl = curl_init();//如果有配置代理这里就设置代理
//        if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"
//            && WxPayConfig::CURL_PROXY_PORT != 0){
//            curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
//            curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
//        }curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_HTTPHEADER, $header);curl_setopt($curl, CURLOPT_HEADER, false);curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($curl, CURLOPT_POST, TRUE);curl_setopt($curl, CURLOPT_POSTFIELDS, $data);if ($useCert == true) {// 设置证书:cert 与 key 分别属于两个.pem文件curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');curl_setopt($curl, CURLOPT_SSLCERT, $sslCert['certPem']);curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');curl_setopt($curl, CURLOPT_SSLKEY, $sslCert['keyPem']);}$result = curl_exec($curl);curl_close($curl);return $result;}

订单查询

/*** 订单查询* @param $out_trade_no* @return mixed* @throws BaseException*/public function orderquery(){$transaction_id = '4200000712202007274705432240';//微信订单号// 当前时间$time = time();// 生成随机字符串$nonce_str = md5($time . mt_rand(00000,99999));//API参数$params = ['appid'        => config('pay.APPID'),             //公众号ID'mch_id'       => config('pay.MCHID'),  //商户号'transaction_id' => $transaction_id,            //商户订单号'nonce_str'    => $nonce_str,             // 随机字符串];//生成签名$params['sign'] = $this->makeSign($params);//请求API$url = 'https://api.mch.weixin.qq.com/pay/orderquery';$result = $this->post($url, $this->toXml($params));$prepay = $this->fromXml($result);// 请求失败if ($prepay['return_code'] === 'FAIL') {throw new BaseException(['msg' => $prepay['return_msg'], 'code' => 0]);}if ($prepay['result_code'] === 'FAIL') {throw new BaseException(['msg' => $prepay['err_code_des'], 'code' => 0]);}return $prepay;}

退款查询

/*** 退款查询* @param $out_trade_no* @return mixed* @throws BaseException*/public function refundquery(){$transaction_id = '4200000712202007274705432240';//微信订单号// 当前时间$time = time();// 生成随机字符串$nonce_str = md5($time . mt_rand(00000,99999));//API参数$params = ['appid'        => config('pay.APPID'),             //公众号ID'mch_id'       => config('pay.MCHID'),  //商户号'transaction_id' => $transaction_id,            //商户订单号'nonce_str'    => $nonce_str,             // 随机字符串];//生成签名$params['sign'] = $this->makeSign($params);//请求API$url = 'https://api.mch.weixin.qq.com/pay/refundquery';$result = $this->post($url, $this->toXml($params));$prepay = $this->fromXml($result);dump($prepay);die;// 请求失败if ($prepay['return_code'] === 'FAIL') {throw new BaseException(['msg' => $prepay['return_msg'], 'code' => 0]);}if ($prepay['result_code'] === 'FAIL') {throw new BaseException(['msg' => $prepay['err_code_des'], 'code' => 0]);}return $prepay;}

支付成功,进行回调

public function index(){$data = file_get_contents('php://input');$data = $this->FromXml($data);tp_log('支付回调数据===>' . json_encode($data), 'index', request()->controller());// 保存微信服务器返回的签名sign$data_sign = $data['sign'];// sign不参与签名算法unset($data['sign']);$sign = $this->makeSign($data);//回调验证签名$str_success = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';$str_error = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';if (($sign === $data_sign) && ($data['return_code'] == 'SUCCESS') && ($data['result_code'] == 'SUCCESS')) {// 支付成功 进行你的逻辑处理}
echo $str_success;//str_error  告知微信 你已的逻辑处理完毕 不用再推送或再次推送你结果}

退款成功 进行回调

/** 小程序 退款结果通知*/public function refund(){$data = file_get_contents('php://input');$data = $this->FromXml($data);tp_log('退款回调数据===>' . json_encode($data), 'refund', request()->controller());//对加密的字符串解密$req_info_xml = openssl_decrypt(base64_decode($data['req_info']), 'aes-256-ecb', md5(config('pay.KEY')),OPENSSL_RAW_DATA);$req_info = $this->FromXml($req_info_xml);//        // 保存微信服务器返回的签名sign
//        $data_sign = $data['sign'];
//        // sign不参与签名算法
//        unset($data['sign']);
//        $sign = $this->makeSign($data);//回调验证签名
//
//        $str_success = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
//        $str_error = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
//
//
//
//        if (($sign === $data_sign) && ($data['return_code'] == 'SUCCESS') && ($data['result_code'] == 'SUCCESS')) {
//            tp_log('退款成功===>', 'refund', request()->controller());
//            //去修改订单的状态 和支付回调的一样 修改成功 告知微信 不在推送
//        }}

用到的方法

/*** 生成签名* @param $values* @return string 本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值*/private function makeSign($values){//签名步骤一:按字典序排序参数ksort($values);$string = $this->toUrlParams($values);//签名步骤二:在string后加入KEY$string = $string . '&key=' . config('pay.KEY');//签名步骤三:MD5加密$string = md5($string);//签名步骤四:所有字符转为大写$result = strtoupper($string);return $result;}private function ToUrlParams($array){$buff = "";foreach ($array as $k => $v) {if ($k != "sign" && $v != "" && !is_array($v)) {$buff .= $k . "=" . $v . "&";}}$buff = trim($buff, "&");return $buff;}/*** 输出xml字符* @param $values* @return bool|string*/private function toXml($values){if (!is_array($values)|| count($values) <= 0) {return false;}$xml = "<xml>";foreach ($values as $key => $val) {if (is_numeric($val)) {$xml .= "<" . $key . ">" . $val . "</" . $key . ">";} else {$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";}}$xml .= "</xml>";return $xml;}/*** 将xml转为array* @param $xml* @return mixed*/private function fromXml($xml){// 禁止引用外部xml实体libxml_disable_entity_loader(true);return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);}/*** 获取cert证书文件* @return array* @throws BaseException*/private function getCertPem(){
//        if (empty($this->config['cert_pem']) || empty($this->config['key_pem'])) {
//            throw new BaseException(['msg' => '请先到后台小程序设置填写微信支付证书文件']);
//        }// cert目录$filePath = EXTEND_PATH.'wxpay/cert/';return ['certPem' => $filePath . 'apiclient_cert.pem','keyPem' => $filePath . 'apiclient_key.pem'];}
/*** 生成商户订单号*/public function get_orderssh(){return date("YmdHis") . mt_rand(10000000, 99999999);}

证书路径:

config配置

微信小程序支付 退款 订单查询 退款查询相关推荐

  1. 关于微信小程序云开发,申请退款接口返回“订单不存在”的问题

    关于微信小程序云开发,申请退款接口返回"订单不存在"的问题 微信支付的退款接口返回"订单不存在",有可能是因为传入的商户订单号或微信订单号有误,但本文要讲的是关 ...

  2. 微信小程序支付以及退款功能(超详细)

    Springboot整合微信小程序支付 第一步: 第二步:导入微信支付的依赖 第三步:在springboot核心配置文件中配置参数 第四步:创建配置类WxPayAppConfig 第五步:支付方法 s ...

  3. 微信小程序支付退款功能

    微信小程序支付退款功能 2022年02月做了一个微信小程序前端+ASP.NET后台的微信退款功能.功能的基本原理是使用JSAPI方式,对接之前的微信支付功能差不多.也是要签名,校验等.只不过它的退款传 ...

  4. php做一个微信退款,php如何实现微信小程序支付及退款

    微信小程序支付的主要逻辑集中在后端,前端只需携带支付所需的数据请求后端接口然后根据返回结果做相应成功失败处理即可. 支付步骤前端请求支付 后端请求微信服务器 后端接受微信服务器返回数据 前端发起支付 ...

  5. 微信小程序支付,查询和支付回调

    微信支付经常用到,做个详细的demo!!! 为了配置好更换,我一般都是把配置放在数据库. pom依赖 <!--微信支付--><dependency><groupId> ...

  6. 微信小程序支付返回签名错误_java 微信小程序微信支付统一下订单及数字签名错误问题(后端)...

    今天来分享一下之前做微信小程序微信支付遇到的一些坑,博主这里是微信小程序支付功能,因此选择的微信支付方式是JSAPI支付方式(温馨提示左下角有音乐哦). 首先我们肯定是要在小程序后台绑定一个商户号的, ...

  7. 微信小程序支付java服务端集成采坑总结

    先上个微信小程序支付官方文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8 重点看 ...

  8. SpringBoot对接微信小程序支付功能开发(一,下单功能)

    1,接入前准备: 接入模式选择直连模式: 申请小程序,得到APPID,并开通微信支付: 申请微信商户号,得到mchid,并绑定APPID: 配置商户API key,下载并配置商户证书,根据微信官方文档 ...

  9. 微信相关-微信小程序支付的实现(详细的一批版)

    微信相关-微信小程序支付的实现 本人只是个半只脚踏进门槛的JAVA后端,以下代码主要是记录我学到的新东西,所以前端需要各位大佬自己去搞了 目录 微信相关-微信小程序支付的实现 一.准备工作(很重要) ...

  10. .NET Core 微信小程序支付——(统一下单)

    最近公司研发了几个电商小程序,还有一个核心的电商直播,只要是电商一般都会涉及到交易信息,离不开支付系统,这里我们统一实现小程序的支付流程(与服务号实现步骤一样). 目录 1.开通小程序的支付能力 2. ...

最新文章

  1. vant组件实现上传图片裁剪_如何用 120 行代码,实现交互完整的拖拽上传组件?...
  2. 网络工程师考试部分技术要点
  3. 给QTreeWidget添加右键菜单功能
  4. 效能优化实践:C/C++单元测试万能插桩工具
  5. 前端学习(570):margin负值下的等高布局
  6. jmeter简单实践(九)
  7. 编写技术解决方案思路
  8. c语言公路竖曲线要素代码,竖曲线要素
  9. 计算机无法安装网卡驱动,win7网卡驱动安装不了怎么修复_WIN7网卡驱动装不上如何解决...
  10. JAVA第五课:正则表达式
  11. 最近3年股息率最高排名
  12. 2007.5 同航驾驶培训公司网站
  13. http简介以及常见知识和http请求头,响应头,状态码,内容类型对照表分享(超实用)
  14. 面试送命题,你为什么从上家公司离职?(面试题总结大全)
  15. VC 使用IE、火狐或默认浏览器打开网页ShellExecute
  16. 2022-2028年中国滚动轴承行业市场发展规模及投资机会分析报告
  17. linux 搭建Discuz论坛教程-个人实践笔记
  18. python:numpy从数组中随机抽取元素
  19. 导数几何意义应用思维导图【试编辑】
  20. java扫雷设计_毕业设计Java版扫雷的设计与实现介绍

热门文章

  1. 百度地图-将经纬度转化为地址
  2. 北京计算机信息学院,北京信息科技大学计算机学院
  3. 4.4-软件开发中,“UI设计图”的作用与绘制方法说明
  4. /etc/fstab详细参数配置
  5. Quartz_2.2.X学习系列四: Tutorials - Lesson 4: More About Triggers
  6. python和工程造价_不会Python的将慢慢被淘汰!
  7. 语句SELECT TOP 100 PERCENT在不同数据库中的区别
  8. p5140大吉大利 晚上吃鸡
  9. 作为IT面试官,我如何考核计算机专业毕业生?作为培训班老师,我又如何提升他们?
  10. 商业分析师的要求与必备技能