基于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
一次编写,随处运行
Oct 09 PHP
简单的用PHP编写的导航条程序
Oct 09 PHP
hadoop常见错误以及处理方法详解
Jun 19 PHP
解析php中如何调用用户自定义函数
Aug 06 PHP
php读取csv文件后,uft8 bom导致在页面上显示出现问题的解决方法
Aug 10 PHP
phpstrom使用xdebug配置方法
Dec 17 PHP
php截取字符串函数分享
Feb 02 PHP
php单例模式示例分享
Feb 12 PHP
PHP测试成功的邮件发送案例
Oct 26 PHP
PHP基于GD库的图像处理方法小结
Sep 27 PHP
Yii输入正确验证码却验证失败的解决方法
Jun 06 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
打造计数器DIY三步曲(下)
2006/10/09 PHP
PHP 图像尺寸调整代码
2010/05/26 PHP
php5.5中类级别的常量使用介绍
2013/10/02 PHP
php查询mysql大量数据造成内存不足的解决方法
2015/03/04 PHP
7个鲜为人知却非常实用的PHP函数
2015/07/01 PHP
php数据结构之顺序链表与链式线性表示例
2018/01/22 PHP
JavaScript window.setTimeout() 的详细用法
2009/11/04 Javascript
jquery Moblie入门—hello world的示例代码学习
2013/01/08 Javascript
jQuery不间断滚动效果(模拟百度新闻支持文字/图片/垂直滚动)
2013/02/05 Javascript
怎么选择Javascript框架(Javascript Framework)
2013/11/22 Javascript
javascript中2个感叹号的用法实例详解
2014/09/04 Javascript
浅谈javascript中字符串String与数组Array
2014/12/31 Javascript
jquery实现左右滑动菜单效果代码
2015/08/27 Javascript
详解javascript实现自定义事件
2016/01/19 Javascript
jQuery的框架介绍
2016/05/11 Javascript
浅谈在js传递参数中含加号(+)的处理方式
2016/10/11 Javascript
Vue 短信验证码组件开发详解
2017/02/14 Javascript
[02:04]2014DOTA2国际邀请赛 DK一个时代的落幕
2014/07/21 DOTA
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
Python Flask 搭建微信小程序后台详解
2019/05/06 Python
Python3.x+迅雷x 自动下载高分电影的实现方法
2020/01/12 Python
Sunglasses Shop荷兰站:英国最大的太阳镜独立在线零售商和供应商
2017/01/08 全球购物
英国Flybe航空官网:欧洲最大的独立支线廉价航空公司
2019/07/15 全球购物
不开辟用于交换数据的临时空间,如何完成字符串的逆序
2012/12/02 面试题
工程力学专业毕业生求职信
2013/10/06 职场文书
个人思想理论学习的自我鉴定
2013/11/30 职场文书
剪彩仪式主持词
2014/03/19 职场文书
公司委托书格式范文
2014/04/04 职场文书
活动倡议书范文
2014/05/13 职场文书
设计专业自荐信
2014/06/19 职场文书
就业协议书怎么填
2014/09/15 职场文书
统计学教授推荐信
2014/09/18 职场文书
共青团员自我评价
2015/03/10 职场文书
道歉的话语大全
2015/05/12 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
2016年小学“我们的节日·中秋节”活动总结
2016/04/05 职场文书