[ ['name' => 'code', 'title' => 'code', 'require' => true, 'type' => 'string'], ], 'create_qrcode' => [ ['name' => 'scene', 'title' => 'scene', 'require' => true, 'type' => 'string'], ['name' => 'page', 'title' => 'page', 'require' => true, 'type' => 'string'], ['name' => 'width', 'title' => 'width', 'require' => true, 'type' => 'numeric'], ['name' => 'dir', 'title' => '文件夹', 'require' => false, 'type' => 'string', 'default' => ""], ], 'createorder' => [ ['name' => 'openid', 'title' => 'openid', 'require' => true, 'type' => 'string'], ['name' => 'total_fee', 'title' => '支付费用', 'require' => true, 'type' => 'numeric'], //以分为单位 ['name' => 'body', 'title' => '支付说明', 'require' => true, 'type' => 'string'], ['name' => 'out_trade_no', 'title' => '商户支付单号', 'require' => true, 'type' => 'string'], ['name' => 'notify_url', 'title' => '回调地址', 'require' => true, 'type' => 'string'], ['name' => 'trade_type', 'title' => 'trade_type', 'require' => true, 'type' => 'string'], ], ]; return $list; } /** * 获取小程序配置信息 * * @return void * @author wj * @date 2022-07-22 */ public function getselfwxconfig() { $config = [ //'appid' => 'wx47d6be96fb2d466c', //'appSecret' => 'c0252b0cea090a1f3fb41ea7c71d55d6', 'appid' => 'wxcacf6eb6e7478e29', 'appSecret' => '3722c3f95df0569498a0e32ae6e85153', ]; return $config; } /** * 获取商户配置信息 * * @return void * @author wj * @date 2022-07-22 */ public function getpayconfig() { $config = [ 'mchid' => '1616316171', //零散务工工会 'key' => 'WaterCat20211001ShuiMaoGongJiang', //商户号key ]; return $config; } private function curl_get($url, &$httpCode = 0) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //不做证书校验,部署在linux环境下请改为true curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); $file_contents = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return $file_contents; } private function getAccessToken() { $config = $this->getselfwxconfig(); $appid = $config['appid']; $appSecret = $config['appSecret']; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appSecret; $result = $this->curl_get($url); $wxResult = json_decode($result, true); return $wxResult; } //开启curl post请求 private function sendCmd($url, $data) { $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检测 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在 curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:')); //解决数据包大不能提交 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包 curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 $tmpInfo = curl_exec($curl); // 执行操作 if (curl_errno($curl)) { echo 'Errno' . curl_error($curl); } curl_close($curl); // 关键CURL会话 return $tmpInfo; // 返回数据 } /** * 获取openid * 20220118 * wj * code 必填 */ public function getOpenid($arr) { $result = $this->checkparam(__FUNCTION__, $arr); if (1 != $result['status']) { return $result; } $data = $result['data']; $code = $data['code']; $config = $this->getselfwxconfig(); $appid = $config['appid']; $appSecret = $config['appSecret']; $wxUrl = 'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code'; $getUrl = sprintf($wxUrl, $appid, $appSecret, $code); $result = $this->curl_get($getUrl); $wxResult = json_decode($result, true); Log::info($wxResult); if (empty($wxResult)) { return backarr(0, "无返回数据"); } $logfail = array_key_exists('errcode', $wxResult); if ($logfail) { return backarr(0, 'error', $logfail['errmsg']); } $openid = $wxResult['openid']; $data = ['openid' => $openid]; if (isset($wxResult['unionid'])) { $unionid = $wxResult['unionid']; $m_wu = new wxusermodel(); $result = $m_wu->updateunionidbyopenid($openid, $unionid); if (empty($result['status'])) { return backarr(0, $result['msg']); } } return backarr(1, 'success', $data); } //获得二维码 public function create_qrcode($arr) { $result = $this->checkparam(__FUNCTION__, $arr); if (1 != $result['status']) { return $result; } $data = $result['data']; $scene = $data['scene']; $width = $data['width']; $page = $data['page']; $dir = $data['dir']; $qr_path = "./Uploads/"; if (empty($dir)) { $dir = 'default'; } $uploaddir = $qr_path . 'qrcode/' . $dir . "/"; $getdir = '/Uploads/qrcode/' . $dir . "/"; if (!file_exists($uploaddir)) { mkdir($uploaddir, 0700, true); //判断保存目录是否存在,不存在自动生成文件目录 } $filename = time() . '.png'; $file = $uploaddir . $filename; $getdir .= $filename; $access = $this->getAccessToken(); $access_token = $access['access_token']; $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $access_token; $qrcode = array( 'scene' => $scene, //二维码所带参数 'width' => $width, 'page' => $page, //二维码跳转路径(要已发布小程序) 'auto_color' => true, ); $result = $this->sendCmd($url, json_encode($qrcode)); //请求微信接口 Log::info($result); $errcode = json_decode($result, true)['errcode']; $errmsg = json_decode($result, true)['errmsg']; if ($errcode) { return backarr(0, $errmsg); } $res = file_put_contents($file, $result); //将微信返回的图片数据流写入文件 if ($res === false) { return backarr(0, '生成二维码失败'); } else { $path = getselfurl('default') . $getdir; return backarr(1, 'success', ['path' => $path]); } } /** * 创建支付订单 统一下单接口 * * @param [type] $arr * @return void * @author wj * @date 2022-07-22 */ public function createorder($arr) { $result = $this->checkparam(__FUNCTION__, $arr); if (1 != $result['status']) { return $result; } $data = $result['data']; $openid = $data['openid']; $total_fee = $data['total_fee']; $body = $data['body']; $out_trade_no = $data['out_trade_no']; $notify_url = $data['notify_url']; $trade_type = $data['trade_type']; //$wid = $data['wid']; $appointentid = $data['appointent_id']; $payconfig = $this->getpayconfig(); $mchid = $payconfig['mchid']; $key = $payconfig['key']; $nonce_str = getRandomStrings($mchid); $config = $this->getselfwxconfig(); $appid = $config['appid']; $data = [ 'appid' => $appid, 'mch_id' => $mchid, 'nonce_str' => $nonce_str, 'openid' => $openid, 'body' => $body, 'out_trade_no' => $out_trade_no, 'total_fee' => $total_fee, 'spbill_create_ip' => '8.8.8.8', 'notify_url' => $notify_url, 'trade_type' => $trade_type, ]; $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; ksort($data); $sign_str = $this->ToUrlParams($data); $sign_str = $sign_str . "&key=" . $key; $data['sign'] = strtoupper(md5($sign_str)); $xml = $this->arrayToXml($data); log::info($xml); $r = $this->postXmlCurl($xml, $url, true); log::info($r); $result = json_decode($this->xml_to_json($r)); log::info($result); //保留这个做记录,以便出错后查询 if ($result->return_code == 'SUCCESS') { if ($result->result_code == 'FAIL') { $msg = $result->err_code_des; return backarr(0, $msg); } $sdata['appId'] = $appid; $sdata['timeStamp'] = time(); $sdata['nonceStr'] = md5(time() . rand() . rand() . $openid); $sdata['package'] = "prepay_id=" . $result->prepay_id; $sdata['signType'] = "MD5"; $payorder['openid'] = $openid; $payorder['prepay_id'] = $result->prepay_id; $payorder['create_date'] = date('Y-m-d H:i:s'); $payorder['payfee'] = $data['total_fee']; $payorder['outorderno'] = $data['out_trade_no']; $payorder['order_type'] = 1; //$payorder['wid'] = $wid; $payorder['appointent_id'] = $appointentid; $l_po = new payordermodel(); $poid = $l_po->insertData($payorder); if (empty($poid)) { return backarr(0, '订单创建失败'); } ksort($sdata); $sign_str = $this->ToUrlParams($sdata); $sign_str = $sign_str . "&key=" . $key; $sdata['paySign'] = strtoupper(md5($sign_str)); $sdata['outorderno'] = $data['out_trade_no']; return backarr(1, '订单创建成功', $sdata); } } /* * 用于微信支付转换认证的信息用的 * by:leoyi * date:2018-4-8 */ public function ToUrlParams($data) { $buff = ""; foreach ($data as $k => $v) { if ($k != "sign" && $v != "" && !is_array($v)) { $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /* * 微信支付-数组转xml * by:leoyi * date:2018-4-8 */ public function arrayToXml($arr) { $xml = ""; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . ""; } else { $xml .= "<" . $key . ">"; } } $xml .= ""; return $xml; } /* * 微信支付-数组转xml * by:leoyi * date:2018-4-8 */ public function xml_to_json($xmlstring) { return json_encode($this->xml_to_array($xmlstring), JSON_UNESCAPED_UNICODE); } /* * 把xml转换成array * by:leoyi * Date:2018-4-11 */ public function xml_to_array($xml) { //return ((array) simplexml_load_string($xmlstring)); return simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); //return json_decode(xml_to_json($xmlstring)); } /** * 用户post方法请求xml信息用的 支付用 * @author write by leoyi 2018-04-8 */ public function postXmlCurl($xml, $url, $useCert = false, $second = 10) { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //严格校验2 //设置header curl_setopt($ch, CURLOPT_HEADER, false); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //运行curl $data = curl_exec($ch); //返回结果 if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return $error; } } /** * 微信回调返回信息 * * @param [type] $data * @return void * @author wj * @date 2022-07-23 */ public function paybackxml($data) { $xmlback = $this->arrayToXml($data); Log::info('返回信息'); Log::info($xmlback); exit($xmlback); } }