基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作


Posted in PHP onAugust 17, 2020

微信小程序或微信支付相关操作支付退款订单查询退款查询支付成功,进行回调退款成功 进行回调用到的方法

支付

/**
 * 预支付请求接口(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(); //商户订单号
 //组装支付数据
 $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);
 }

证书路径

基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作

config配置

基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作

总结

到此这篇关于基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询的文章就介绍到这了,更多相关微信小程序支付 退款 订单查询 退款查询内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
十天学会php之第六天
Oct 09 PHP
一个PHP并发访问实例代码
Sep 06 PHP
thinkphp模板输出技巧汇总
Nov 24 PHP
PHP中使用Imagick操作PSD文件实例
Jan 26 PHP
Apache连接PHP后无法启动问题解决思路
Jun 18 PHP
隐藏Nginx或Apache以及PHP的版本号的方法
Jan 03 PHP
php上传图片获取路径及给表单字段赋值的方法
Jan 23 PHP
PHP实现简易blog的制作
Oct 24 PHP
PHP获取数组中单列值的方法
Jun 10 PHP
PHP基于SimpleXML生成和解析xml的方法示例
Jul 17 PHP
浅谈laravel框架sql中groupBy之后排序的问题
Oct 17 PHP
php7 图形用户界面GUI 开发示例
Feb 22 PHP
PhpStorm2020.1 安装 debug - Postman 调用的详细教程
Aug 17 #PHP
php开发最强大的IDE编辑的phpstorm 2020.2配置Xdebug调试的详细教程
Aug 17 #PHP
PHP unset函数原理及使用方法解析
Aug 14 #PHP
PHP常量及变量区别原理详解
Aug 14 #PHP
PHP获取当前时间不准确问题解决方案
Aug 14 #PHP
PHP语言对接抖音快手小红书视频/图片去水印API接口源码
Aug 11 #PHP
php实现微信和支付宝支付的示例代码
Aug 11 #PHP
You might like
php基础知识:类与对象(3) 构造函数和析构函数
2006/12/13 PHP
PHP测试程序运行时间的类
2012/02/05 PHP
php生成excel列序号代码实例
2013/12/24 PHP
PHP解析html类库simple_html_dom的转码bug
2014/05/22 PHP
thinkphp autoload 命名空间自定义 namespace
2015/07/17 PHP
PHP面试常用算法(推荐)
2016/07/22 PHP
ThinkPHP 3使用OSS的方法
2018/07/19 PHP
PHP中“=&gt;
2019/03/01 PHP
原生PHP实现导出csv格式Excel文件的方法示例【附源码下载】
2019/03/07 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
EXT窗口Window及对话框MessageBox
2011/01/27 Javascript
jquery中获取元素的几种方式小结
2011/07/05 Javascript
基于jquery的时间段实现代码
2012/08/02 Javascript
JavaScript 32位整型无符号操作示例
2013/12/08 Javascript
VsCode插件整理(小结)
2017/09/14 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
一个Vue视频媒体多段裁剪组件的实现示例
2018/08/09 Javascript
ExtJs使用自定义插件动态保存表头配置(隐藏或显示)
2018/09/25 Javascript
VUE+elementui面包屑实现动态路由详解
2019/11/04 Javascript
微信小程序图片自适应实现解析
2020/01/21 Javascript
JavaScript enum枚举类型定义及使用方法
2020/05/15 Javascript
JavaScript隐式类型转换代码实例
2020/05/29 Javascript
[01:45]IMBATV TI4前线报道-选手到达
2014/07/07 DOTA
使用Python的Tornado框架实现一个一对一聊天的程序
2015/04/25 Python
python 产生token及token验证的方法
2018/12/26 Python
python实现beta分布概率密度函数的方法
2019/07/08 Python
基于Python的ModbusTCP客户端实现详解
2019/07/13 Python
CSS3教程(4):网页边框和网页文字阴影
2009/04/02 HTML / CSS
Erwin Müller穆勒家居瑞士官网:您整个家庭的邮购公司
2019/12/28 全球购物
农村门前三包责任书
2014/07/25 职场文书
介绍信范文大全
2015/05/07 职场文书
国庆放假通知怎么写
2015/07/30 职场文书
2019奶茶店创业计划书范本!
2019/07/15 职场文书
创业分两种人:那么哪些适合创业?,哪些适合不适合创业呢?
2019/08/23 职场文书
个人房屋租赁合同(标准范本)
2019/09/16 职场文书
windows11怎么查看自己安装的版本号? win11版本号的查看方法
2021/11/21 数码科技