一、Model层,Wxpay.PHP
<?PHP namespace app\common\model; class Wxpay { private $appid = 'wxe8*****d4'; //微信公众号appid private $secret = '37c4*******5f0'; //微信公众号appsecret private $mchid = '13******02'; //商家号 private $key = '5363e******49e8'; //支付密钥 private $sslcert_path = 'apiclient_cert.pem'; //证书所在绝对路径 private $sslkey_path = 'apiclient_key.pem'; //证书所在绝对路径 public function __construct($appid = '', $secret = '', $mchid = '', $key = '') { if(!empty($appid)) $this->appid = $appid; if(!empty($secret)) $this->secret = $secret; if(!empty($mchid)) $this->mchid = $mchid; if(!empty($key)) $this->key= $key; } /* * 微信内H5调起支付 * @params string $openid : 微信用户openid * @params string $out_Trade_no : 商家生成的订单号(唯一性) * @params int $total_fee : 支付金额,单位分 * return array $ret : 返回支付时所需要的数据 * */ public function payForWeixin($openid,$out_Trade_no,$total_fee,$attach='微信支付',$body='微信支付') { //支付数据 $data['openid'] = $openid; $data['out_Trade_no'] = $out_Trade_no; $data['total_fee'] = $total_fee*100; $data['spbill_create_ip'] = $_SERVER[REMOTE_ADDR]; $data['attach'] = $attach; $data['body'] = $body; $data['appid'] = $this->appid; $data['mch_id'] = $this->mchid; $data['nonce_str'] = random(12); $data['Trade_type'] = JSAPI; $data['notify_url'] = http://****.com/home/wxpaynofiy/notify.html; $sign = $this->getParam($data); $dataxML = <xml> <appid>.$data['appid'].</appid> <attach>.$data['attach'].</attach> <body>.$data['body'].</body> <mch_id>.$data['mch_id'].</mch_id> <nonce_str>.$data['nonce_str'].</nonce_str> <notify_url>.$data['notify_url'].</notify_url> <openid>.$data['openid'].</openid> <out_Trade_no>.$data['out_Trade_no'].</out_Trade_no> <spbill_create_ip>.$data['spbill_create_ip'].</spbill_create_ip> <total_fee>.$data['total_fee'].</total_fee> <Trade_type>.$data['Trade_type'].</Trade_type> <sign>.$sign.</sign> </xml>; $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $result = $this->https_post($url,$dataxML); $ret = $this->xmlToArray($result); if($ret['return_code'] == 'SUCCESS' && $ret['return_msg'] == 'OK') { return array( 'appId' => $this->appid, 'timeStamp' => time(), 'nonceStr' => $data['nonce_str'], 'package' => 'prepay_id='.$ret['prepay_id'], 'signType' => 'MD5', 'paySign' => $sign ); } else { $this->errorLog(微信支付失败,,$ret); return null; } } /* * 微信二维码支付 * @params string $openid : 用户的openid * @params string $out_Trade_no : 商户订单号 * @params number $total_fee : 订单金额,单位分 * return string $code_url : 二维码URL链接 */ public function payForQrcode($out_Trade_no,$total_fee,$body=魔盒CMS,$attach=微信支付) { //支付数据 $data['out_Trade_no'] = $out_Trade_no; $data['total_fee'] = $total_fee*100; $data['spbill_create_ip'] = $_SERVER[REMOTE_ADDR]; $data['attach'] = $attach; $data['body'] = $body; $data['appid'] = $this->appid; $data['mch_id'] = $this->mchid; $data['nonce_str'] = random(12); $data['Trade_type'] = NATIVE; $data['notify_url'] = http://****.com/home/wxpaynofiy/notify.html; $sign = $this->getParam($data); $dataxML = <xml> <appid>.$data['appid'].</appid> <attach>.$data['attach'].</attach> <body>.$data['body'].</body> <mch_id>.$data['mch_id'].</mch_id> <nonce_str>.$data['nonce_str'].</nonce_str> <notify_url>.$data['notify_url'].</notify_url> <out_Trade_no>.$data['out_Trade_no'].</out_Trade_no> <spbill_create_ip>.$data['spbill_create_ip'].</spbill_create_ip> <total_fee>.$data['total_fee'].</total_fee> <Trade_type>.$data['Trade_type'].</Trade_type> <sign>.$sign.</sign> </xml>; $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; $result = $this->https_post($url,$dataxML); $ret = $this->xmlToArray($result); if($ret['return_code'] == 'SUCCESS' && $ret['return_msg'] == 'OK') { return $ret['code_url']; } else { $this->errorLog(获取微信支付二维码失败,,$ret); return null; } } /* * 订单查询 * @params string $transaction_id : 微信订单号 * @params string $out_Trade_no : 商家订单号(与微信订单号二选一) * */ public function findOrder($out_Trade_no) { $data['appid'] = $this->appid; $data['mch_id'] = $this->mchid; $data['nonce_str'] = random(12); $data['out_Trade_no'] = $out_Trade_no; $sign = $this->getParam($data); $dataxML = <xml> <appid>.$data['appid'].</appid> <mch_id>.$data['mch_id'].</mch_id> <nonce_str>.$data['nonce_str'].</nonce_str> <out_Trade_no>.$data['out_Trade_no'].</out_Trade_no> <sign>.$sign.</sign> </xml>; $url = 'https://api.mch.weixin.qq.com/pay/orderquery'; $result = $this->https_post($url,$dataxML); $ret = $this->xmlToArray($result); if($ret['return_code'] == 'SUCCESS' && $ret['return_msg'] == 'OK') { return $ret; } else { $this->errorLog(查询微信支付订单失败,,$ret); return null; } } /* * 退款订单查询 * @params string $transaction_id : 微信订单号 * @params string $out_Trade_no : 商家订单号(与微信订单号二选一) * */ public function findrefundOrder($out_Trade_no) { $data['appid'] = $this->appid; $data['mch_id'] = $this->mchid; $data['nonce_str'] = random(12); $data['out_Trade_no'] = $out_Trade_no; $sign = $this->getParam($data); $dataxML = <xml> <appid>.$data['appid'].</appid> <mch_id>.$data['mch_id'].</mch_id> <nonce_str>.$data['nonce_str'].</nonce_str> <out_Trade_no>.$data['out_Trade_no'].</out_Trade_no> <sign>.$sign.</sign> </xml>; $url = 'https://api.mch.weixin.qq.com/pay/refundquery'; $result = $this->https_post($url,$dataxML); $ret = $this->xmlToArray($result); if($ret['return_code'] == 'SUCCESS' && $ret['return_msg'] == 'OK') { return $ret; } else { $this->errorLog(查询微信支付退款订单失败,,$ret); return $ret['err_code_des']; } } /* * 申请退款 * @params string $out_Trade_no : 商户订单号 * @params string $out_refund_no : 商户退款单号 * @params int $total_fee : 订单金额 * @params int $refund_fee : 退款金额 * @params string $refund_desc : 退款原因 * */ public function refund($out_Trade_no,$out_refund_no,$total_fee,$refund_fee,$refund_desc='退款') { $data['appid'] = $this->appid; $data['mch_id'] = $this->mchid; $data['nonce_str'] = random(12); $data['out_Trade_no'] = $out_Trade_no; $data['out_refund_no'] = $out_refund_no; $data['total_fee'] = $total_fee*100; $data['refund_fee'] = $refund_fee*100; $data['refund_desc'] = $refund_desc; $data['notify_url'] = http://*****.com/home/wxpaynofiy/refund.html; $sign = $this->getParam($data); $dataxML = <xml> <appid>.$data['appid'].</appid> <mch_id>.$data['mch_id'].</mch_id> <nonce_str>.$data['nonce_str'].</nonce_str> <out_Trade_no>.$data['out_Trade_no'].</out_Trade_no> <out_refund_no>.$data['out_refund_no'].</out_refund_no> <total_fee>.$data['total_fee'].</total_fee> <refund_fee>.$data['refund_fee'].</refund_fee> <refund_desc>.$data['refund_desc'].</refund_desc> <notify_url>.$data['notify_url'].</notify_url> <sign>.$sign.</sign> </xml>; $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund'; $result = $this->https_post($url,$dataxML,true); $ret = $this->xmlToArray($result); if($ret['return_code'] == 'SUCCESS' && $ret['return_msg'] == 'OK') { return $ret; } else { $this->errorLog(微信退款失败,,$ret); return null; } } /* * 企业付款至用户零钱 * @params string $openid : 用户openid * @params int $total_fee : 付款金额,单位分 * @params string $out_Trade_no : 商家订单号 * @params string $username : 微信用户名称(注意微信昵称若为空时支付会出错) * @params string $desc : 付款描述 * @params string $check_name : 是否检测用户名 * */ public function payForUser($openid,$total_fee,$out_Trade_no,$username='魔盒CMS',$desc='魔盒CMS付款给用户',$check_name='NO_CHECK') { $data['amount'] = $total_fee*100; $data['check_name'] = $check_name; $data['desc'] = $desc; $data['mch_appid'] = $this->appid; $data['mchid'] = $this->mchid; $data['nonce_str'] = random(12); $data['openid'] = $openid; $data['partner_Trade_no'] = $out_Trade_no; $data['re_user_name'] = $username; $data['spbill_create_ip'] = $_SERVER[REMOTE_ADDR]; $sign = $this->getParam($data); $dataxML=<xml> <mch_appid>.$data['mch_appid'].</mch_appid> <mchid>.$data['mchid'].</mchid> <nonce_str>.$data['nonce_str'].</nonce_str> <partner_Trade_no>.$data['partner_Trade_no'].</partner_Trade_no> <openid>.$data['openid'].</openid> <check_name>.$data['check_name'].</check_name> <re_user_name>.$data['re_user_name'].</re_user_name> <amount>.$data['amount'].</amount> <desc>.$data['desc'].</desc> <spbill_create_ip>.$data['spbill_create_ip'].</spbill_create_ip> <sign>.$sign.</sign> </xml>; $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; $result = $this->https_post($url,$dataxML,true); $ret = $this->xmlToArray($result); if($ret['return_code']=='SUCCESS' && $ret['result_code'] == 'SUCCESS') { //支付成功返回商户订单号、微信订单号、微信支付成功时间 $result['partner_Trade_no'] = $ret['partner_Trade_no']; $result['payment_no'] = $ret['payment_no']; $result['payment_time'] = $ret['payment_time']; return $ret; } else { $this->errorLog('付款给用户失败',$ret); return null; } } /* * 普通红包 * @params string $out_Trade_no : 商家订单号 * @params string $openid : 接收红包用户的openid * @params int $total_fee : 红包金额,单位分 * @params int $total_num : 红包发放总人数 * @params string $wishing : 红包祝福语 * @params string $act_name : 活动名称 * @params string $remark : 备注 * @params string $scene_id :场景值ID。发放红包使用场景,红包金额大于200或者小于1元时必传。PRODUCT_1:商品促销、PRODUCT_2:抽奖、PRODUCT_3:虚拟物品兑奖 、PRODUCT_4:企业内部福利、PRODUCT_5:渠道分润、PRODUCT_6:保险回馈、PRODUCT_7:彩票派奖、PRODUCT_8:税务刮奖 * */ public function redPack($openid,$total_fee,$out_Trade_no,$total_num = 1,$wishing = '感谢您光临***平台进行购物',$act_name='***购物发红包',$remark = '购物领红包') { $data['mch_billno'] = $out_Trade_no; $data['mch_id'] = $this->mchid; $data['wxappid'] = $this->appid; $data['send_name'] = '发送红包者的名称'; $data['re_openid'] = $openid; $data['total_amount'] = $total_fee; $data['total_num'] = $total_num; $data['wishing'] = $wishing; $data['client_ip'] = $_SERVER[REMOTE_ADDR]; $data['act_name'] = $act_name; $data['remark'] = $remark; $data['nonce_str'] = random(12); $sign = $this->getParam($data); $dataxML=<xml> <sign>.$sign.</sign> <mch_billno>.$data['mch_billno'].</mch_billno> <mch_id>.$data['mch_id'].</mch_id> <wxappid>.$data['wxappid'].</wxappid> <send_name>.$data['send_name'].</send_name> <re_openid>.$data['re_openid'].</re_openid> <total_amount>.$data['total_amount'].</total_amount> <total_num>.$data['total_num'].</total_num> <wishing>.$data['wishing'].</wishing> <client_ip>.$data['client_ip'].</client_ip> <act_name>.$data['act_name'].</act_name> <remark>.$data['remark'].</remark> <nonce_str>.$data['nonce_str'].</nonce_str> </xml>; $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack'; $result = $this->https_post($url,$dataxML,true); $ret = $this->xmlToArray($result); if($ret['return_code']=='SUCCESS' && $ret['result_code'] == 'SUCCESS') { return $ret; } else { $this->errorLog('发放普通红包失败',$ret); return $ret['err_code_des']; } } /* * 裂变红包:一次可以发放一组红包。首先领取的用户为种子用户,种子用户领取一组红包当中的一个,并可以通过社交分享将剩下的红包给其他用户。 * 裂变红包充分利用了人际传播的优势。 * @params string $out_Trade_no : 商家订单号 * @params string $openid : 接收红包用户的openid * @params int $total_fee : 红包金额,单位分 * @params int $total_num : 红包发放总人数 * @params string $wishing : 红包祝福语 * @params string $act_name : 活动名称 * @params string $remark : 备注 * @params string $scene_id :场景值ID。发放红包使用场景,红包金额大于200或者小于1元时必传。PRODUCT_1:商品促销、PRODUCT_2:抽奖、PRODUCT_3:虚拟物品兑奖 、PRODUCT_4:企业内部福利、PRODUCT_5:渠道分润、PRODUCT_6:保险回馈、PRODUCT_7:彩票派奖、PRODUCT_8:税务刮奖 * */ public function redPackGroup($openid,$total_fee,$out_Trade_no,$total_num,$wishing = '感谢您光临***进行购物',$act_name='**购物发红包',$remark = '购物领红包') { $data['mch_billno'] = $out_Trade_no; $data['mch_id'] = $this->mchid; $data['wxappid'] = $this->appid; $data['send_name'] = '发送红包者的名称'; $data['re_openid'] = $openid; $data['total_amount'] = $total_fee; $data['amt_type'] = 'ALL_RAND'; //ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额 $data['total_num'] = $total_num; $data['wishing'] = $wishing; $data['client_ip'] = $_SERVER[REMOTE_ADDR]; $data['act_name'] = $act_name; $data['remark'] = $remark; $data['nonce_str'] = random(12); $sign = $this->getParam($data); $dataxML=<xml> <sign>.$sign.</sign> <mch_billno>.$data['mch_billno'].</mch_billno> <mch_id>.$data['mch_id'].</mch_id> <wxappid>.$data['wxappid'].</wxappid> <send_name>.$data['send_name'].</send_name> <re_openid>.$data['re_openid'].</re_openid> <total_amount>.$data['total_amount'].</total_amount> <amt_type>.$data['amt_type'].</amt_type> <total_num>.$data['total_num'].</total_num> <wishing>.$data['wishing'].</wishing> <client_ip>.$data['client_ip'].</client_ip> <act_name>.$data['act_name'].</act_name> <remark>.$data['remark'].</remark> <nonce_str>.$data['nonce_str'].</nonce_str> </xml>; $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack'; $result = $this->https_post($url,$dataxML,true); $ret = $this->xmlToArray($result); if($ret['return_code']=='SUCCESS' && $ret['result_code'] == 'SUCCESS') { return $ret; } else { $this->errorLog('发放裂变红包失败',$ret); return $ret['err_code_des']; } } /* * 查询红包记录 * @params string $out_Trade_no : 商家订单号 * */ public function findRedPack($out_Trade_no) { $data['mch_billno'] = $out_Trade_no; $data['mch_id'] = $this->mchid; $data['appid'] = $this->appid; $data['bill_type'] = 'MCHT'; //MCHT:通过商户订单号获取红包信息。 $data['nonce_str'] = random(12); $sign = $this->getParam($data); $dataxML=<xml> <sign>.$sign.</sign> <mch_billno>.$data['mch_billno'].</mch_billno> <mch_id>.$data['mch_id'].</mch_id> <appid>.$data['appid'].</appid> <bill_type>.$data['bill_type'].</bill_type> <nonce_str>.$data['nonce_str'].</nonce_str> </xml>; $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo'; $result = $this->https_post($url,$dataxML,true); $ret = $this->xmlToArray($result); if($ret['return_code']=='SUCCESS' && $ret['result_code'] == 'SUCCESS') { return $ret; } else { $this->errorLog('查询红包记录失败',$ret); return $ret['err_code_des']; } } /* * 获取用户微信的OPENID * */ public function openid($c=false) { if($_GET['state']!=zgm){ $t = $c ? snsapi_userinfo : snsapi_base; $url=urlencode(get_url()); $url=https://open.weixin.qq.com/connect/oauth2/authorize?appid=.$this->appid.&redirect_uri=.$url.&response_type=code&scope=.$t.&state=zgm#wechat_redirect; echo <html><script>window.location.href='$url';</script></html>; exit; } if($_GET['code']){ $url=https://api.weixin.qq.com/sns/oauth2/access_token?appid=.$this->appid.&secret=.$this->secret.&code=.$_GET['code'].&grant_type=authorization_code; $wx_db=json_decode($this->https_get($url)); if($c){ $url_2=https://api.weixin.qq.com/sns/userinfo?access_token=.$wx_db->access_token.&openid=.$wx_db->openid.&lang=zh_CN; $db=json_decode($this->https_get($url_2)); return $db; }else{ return $wx_db->openid; } } } /* * 发起网络GET请求 * @params string $url : URL链接 */ private function https_get($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_HEADER, FALSE) ; curl_setopt($curl, CURLOPT_TIMEOUT,60); if (curl_errno($curl)) { return 'Errno'.curl_error($curl); } else{$result=curl_exec($curl);} curl_close($curl); return $result; } //对参数排序,生成MD5加密签名 private function getParam($paramArray, $isencode=false) { $paramStr = ''; ksort($paramArray); $i = 0; foreach ($paramArray as $key => $value) { if ($key == 'Signature'){ continue; } if ($i == 0){ $paramStr .= ''; }else{ $paramStr .= '&'; } $paramStr .= $key . '=' . ($isencode?urlencode($value):$value); ++$i; } $stringSignTemp=$paramStr.&key=.$this->key; $sign=strtoupper(md5($stringSignTemp)); return $sign; } //POST提交数据 private function https_post($url,$data,$ssl = false) { $ch = curl_init (); curl_setopt ( $ch, CURLOPT_URL, $url ); curl_setopt ( $ch, CURLOPT_CUSTomrEQUEST, POST ); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE ); curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE ); if($ssl) { curl_setopt ( $ch,CURLOPT_SSLCERT,$this->sslcert_path); curl_setopt ( $ch,CURLOPT_SSLKEY,$this->sslkey_path); } curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 ); curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 ); curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data ); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); $result = curl_exec($ch); if (curl_errno($ch)) { return 'Errno: '.curl_error($ch); } curl_close($ch); return $result; } /* * XML转array * @params xml $xml : xml 数据 * return array $data : 转义后的array数组 */ private function xmlToArray($xml) { libxml_disable_entity_loader(true); $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); $val = json_decode(json_encode($xmlstring),true); return $val; } /* * 记录日志 * @params string $msg : 提示语句 * @params array $ret : 错误结果 */ private function errorLog($msg,$ret) { file_put_contents(ROOT_PATH . 'runtime/error/wxpay.log', [ . date('Y-m-d H:i:s') . ] .$msg., .json_encode($ret).PHP_EOL, FILE_APPEND); } }
二、Controller层,Test.PHP
<?PHP namespace app\goods\controller; use app\common\model\Wxpay; class Test { /* * 调用微信支付 * 一、获取微信用户的openid; * 二、调用微信支付接口 * 三、生成H5中使用的签名内容 */ public function wx() { $wxpay = new Wxpay(); $openid = $wxpay->openid(); $pay = $wxpay->payForWeixin($openid,date('YmdHis').rand(1,5),'0.1'); $paySign =strtoupper(MD5('appId='.$pay['appId'].'&nonceStr='.$pay['nonceStr'].'&package='.$pay['package'].'&signType=MD5&timeStamp='.$pay['timeStamp'].'&key=536*****9e8')); $h5 = array( 'appId' => $pay['appId'], 'timeStamp' => $pay['timeStamp'], 'nonceStr' => $pay['nonceStr'], 'package' => $pay['package'], 'signType' => $pay['signType'], 'paySign' => $paySign ); $this->assign('wxpay',$h5); return view(); } }
三、HTML中调用微信支付,wx.html
<!DOCTYPE html> <html lang=en> <head> <Meta charset=UTF-8> <title>订单示例</title> </head> <body> <script type=text/javascript> function onBridgeReady(){ WeixinjsBridge.invoke( 'getBrandWCPayRequest', { appId:{$wxpay['appId']}, timeStamp:{$wxpay['timeStamp']}, nonceStr:{$wxpay['nonceStr']}, package:{$wxpay['package']}, signType:MD5, paySign:{$wxpay['paySign']} }, function(res){ if(res.err_msg == get_brand_wcpay_request:ok ){ // 使用以上方式判断前端返回,微信团队郑重提示: //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 } }); } if (typeof WeixinjsBridge == undefined){ if( document.addEventListener ){ document.addEventListener('WeixinjsBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinjsBridgeReady', onBridgeReady); document.attachEvent('onWeixinjsBridgeReady', onBridgeReady); } }else{ onBridgeReady(); } </script> </body> </html>
四、接收微信支付返回结果,支付时设置的notify_url值,确保此链接外网能访问。wxpaynofiy.PHP
<?PHP namespace app\home\controller; class Wxpaynofiy { public function notify() { $xml = isset($GLOBALS[HTTP_RAW_POST_DATA]) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents(PHP://input); $data = xmlToArray($xml); if($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS'){ if($this->checkSign($data)) { $transaction_id = $data['transaction_id']; //微信支付订单号 $out_Trade_no = $data['out_Trade_no']; //商家订单号 $this->errorLog('微信支付返回结果,微信支付订单号:'.$transaction_id.',商家订单号:'.$out_Trade_no,[]); } else { $this->errorLog('微信支付返回结果签名验证失败',$data); } } else { $this->errorLog('微信支付返回结果',$data); } echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; } /* * 验证签名 * @params array $result : 微信支付成功返回的结果数组 * return bool $ret : 成功true,失败false * */ private function checkSign(array $data) { $str = ''; ksort($data); foreach ($data as $k => $v) { if($k != 'sign') $str .= $k.'='.$v.'&'; } $temp = $str . 'key=5363******49e8'; //key:商户支付密钥 $sign = strtoupper(md5($temp)); return $sign == $data['sign'] ? true : false; } private function errorLog($msg,$ret) { file_put_contents(ROOT_PATH . 'runtime/error/wxpaynofiy.log', [ . date('Y-m-d H:i:s') . ] .$msg., .json_encode($ret).PHP_EOL, FILE_APPEND); } }
视频教程 :php微信接口开发实战项目聊天机器人+微信支付