这篇文章主要介绍了关于利用yii2微信后台开发的解析,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
yii2是一个高性能,基于组件的 php 框架,这篇文章详细的给大家介绍了利用yii2开发微信后台。我们一起来看看。
网上有很多关于yii2.0微信开发教程,但是太过复杂凌乱,所以今天在这里给大家整理总结利用yii2微信后台开发的系列了,给需要的小伙伴们参考。
一:接入微信
yii2后台配置
1.在app/config/params.php中配置token参数
return [ //微信接入 'wechat' =>[ 'token' => 'your token', ],];
2.在app/config/main.php中配置路由
因为接口模块使用的restful api,所以需要定义路由规则。
'urlmanager' => [ 'enableprettyurl' => true, 'enablestrictparsing' => true, 'showscriptname' => false, 'rules' => [ [ 'class' => 'yii\rest\urlrule', 'controller' => 'wechat', 'extrapatterns' => [ 'get valid' => 'valid', ], ], ],],
3.在app/controllers中新建wechatcontroller
<?phpnamespace api\controllers;use yii;use yii\rest\activecontroller;class wechatcontroller extends activecontroller{ public $modelclass = ''; public function actionvalid() { $echostr = $_get["echostr"]; $signature = $_get["signature"]; $timestamp = $_get["timestamp"]; $nonce = $_get["nonce"]; //valid signature , option if($this->checksignature($signature,$timestamp,$nonce)){ echo $echostr; } } private function checksignature($signature,$timestamp,$nonce) { // you must define token by yourself $token = yii::$app->params['wechat']['token']; if (!$token) { echo 'token is not defined!'; } else { $tmparr = array($token, $timestamp, $nonce); // use sort_string rule sort($tmparr, sort_string); $tmpstr = implode( $tmparr ); $tmpstr = sha1( $tmpstr ); if( $tmpstr == $signature ){ return true; }else{ return false; } } }}
微信公众号后台配置
在微信公众号后台配置url和token,然后提交验证即可。
url:http://app.demo.com/wechats/validtoken:your token
二:获取用户信息
用户表设计
create table `wechat_user` ( `id` int(11) not null, `openid` varchar(255) collate utf8_unicode_ci not null, `nickname` varchar(50) collate utf8_unicode_ci not null comment '微信昵称', `sex` tinyint(4) not null comment '性别', `headimgurl` varchar(255) collate utf8_unicode_ci not null comment '头像', `country` varchar(50) collate utf8_unicode_ci not null comment '国家', `province` varchar(50) collate utf8_unicode_ci not null comment '省份', `city` varchar(50) collate utf8_unicode_ci not null comment '城市', `access_token` varchar(255) collate utf8_unicode_ci not null, `refresh_token` varchar(255) collate utf8_unicode_ci not null, `created_at` timestamp null default current_timestamp) engine=innodb auto_increment=4 default charset=utf8 collate=utf8_unicode_ci;alter table `wechat_user` add primary key (`id`);
获取用户信息的相关接口
1.用户授权接口:获取access_token、openid等;获取并保存用户资料到数据库
public function actionaccesstoken(){ $code = $_get["code"]; $state = $_get["state"]; $appid = yii::$app->params['wechat']['appid']; $appsecret = yii::$app->params['wechat']['appsecret']; $request_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$appid.'&secret='.$appsecret.'&code='.$code.'&grant_type=authorization_code'; //初始化一个curl会话 $ch = curl_init(); curl_setopt($ch, curlopt_url, $request_url); curl_setopt($ch, curlopt_returntransfer, true); $result = curl_exec($ch); curl_close($ch); $result = $this->response($result); //获取token和openid成功,数据解析 $access_token = $result['access_token']; $refresh_token = $result['refresh_token']; $openid = $result['openid']; //请求微信接口,获取用户信息 $userinfo = $this->getuserinfo($access_token,$openid); $user_check = wechatuser::find()->where(['openid'=>$openid])->one(); if ($user_check) { //更新用户资料 } else { //保存用户资料 } //前端网页的重定向 if ($openid) { return $this->redirect($state.$openid); } else { return $this->redirect($state); }}
2.从微信获取用户资料
public function getuserinfo($access_token,$openid){ $request_url = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$access_token.'&openid='.$openid.'&lang=zh_cn'; //初始化一个curl会话 $ch = curl_init(); curl_setopt($ch, curlopt_url, $request_url); curl_setopt($ch, curlopt_returntransfer, true); $result = curl_exec($ch); curl_close($ch); $result = $this->response($result); return $result;}
3.获取用户资料接口
public function actionuserinfo(){ if(isset($_request["openid"])){ $openid = $_request["openid"]; $user = wechatuser::find()->where(['openid'=>$openid])->one(); if ($user) { $result['error'] = 0; $result['msg'] = '获取成功'; $result['user'] = $user; } else { $result['error'] = 1; $result['msg'] = '没有该用户'; } } else { $result['error'] = 1; $result['msg'] = 'openid为空'; } return $result;}
三:微信支付
1.微信支付接口:打包支付数据
public function actionpay(){ if(isset($_request["uid"])&&isset($_request["oid"])&&isset($_request["totalfee"])){ //uid、oid、totalfee $uid = $_request["uid"]; $oid = $_request["oid"]; $totalfee = $_request["totalfee"]; $timestamp = time(); //微信支付参数 $appid = yii::$app->params['wechat']['appid']; $mchid = yii::$app->params['wechat']['mchid']; $key = yii::$app->params['wechat']['key']; $notifyurl = yii::$app->params['wechat']['notifyurl']; //支付打包 $wx_pay = new wechatpay($mchid, $appid, $key); $package = $wx_pay->createjsbizpackage($uid, $totalfee, $oid, $notifyurl, $timestamp); $result['error'] = 0; $result['msg'] = '支付打包成功'; $result['package'] = $package; return $result; }else{ $result['error'] = 1; $result['msg'] = '请求参数错误'; } return $result;}
2.接收微信发送的异步支付结果通知
public function actionnotify(){ $poststr = $globals["http_raw_post_data"]; $postobj = simplexml_load_string($poststr, 'simplexmlelement', libxml_nocdata); // if ($postobj === false) { die('parse xml error'); } if ($postobj->return_code != 'success') { die($postobj->return_msg); } if ($postobj->result_code != 'success') { die($postobj->err_code); } //微信支付参数 $appid = yii::$app->params['wechat']['appid']; $mchid = yii::$app->params['wechat']['mchid']; $key = yii::$app->params['wechat']['key']; $wx_pay = new wechatpay($mchid, $appid, $key); //验证签名 $arr = (array)$postobj; unset($arr['sign']); if ($wx_pay->getsign($arr, $key) != $postobj->sign) { die("签名错误"); } //支付处理正确-判断是否已处理过支付状态 $orders = order::find()->where(['uid'=>$postobj->openid, 'oid'=>$postobj->out_trade_no, 'status' => 0])->all(); if(count($orders) > 0){ //更新订单状态 foreach ($orders as $order) { //更新订单 $order['status'] = 1; $order->update(); } return '<xml><return_code><![cdata[success]]></return_code><return_msg><![cdata[ok]]></return_msg></xml>'; } else { //订单状态已更新,直接返回 return '<xml><return_code><![cdata[success]]></return_code><return_msg><![cdata[ok]]></return_msg></xml>'; }}
3.微信支付类 wechatpay.php
<?phpnamespace api\sdk;use yii;class wechatpay{ protected $mchid; protected $appid; protected $key; public function __construct($mchid, $appid, $key){ $this->mchid = $mchid; $this->appid = $appid; $this->key = $key; } public function createjsbizpackage($openid, $totalfee, $outtradeno, $ordername, $notifyurl, $timestamp){ $config = array( 'mch_id' => $this->mchid, 'appid' => $this->appid, 'key' => $this->key, ); $unified = array( 'appid' => $config['appid'], 'attach' => '支付', 'body' => $ordername, 'mch_id' => $config['mch_id'], 'nonce_str' => self::createnoncestr(), 'notify_url' => $notifyurl, 'openid' => $openid, 'out_trade_no' => $outtradeno, 'spbill_create_ip' => '127.0.0.1', 'total_fee' => intval($totalfee * 100), 'trade_type' => 'jsapi', ); $unified['sign'] = self::getsign($unified, $config['key']); $responsexml = self::curlpost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arraytoxml($unified)); $unifiedorder = simplexml_load_string($responsexml, 'simplexmlelement', libxml_nocdata); if ($unifiedorder === false) { die('parse xml error'); } if ($unifiedorder->return_code != 'success') { die($unifiedorder->return_msg); } if ($unifiedorder->result_code != 'success') { die($unifiedorder->err_code); } $arr = array( "appid" => $config['appid'], "timestamp" => $timestamp, "noncestr" => self::createnoncestr(), "package" => "prepay_id=" . $unifiedorder->prepay_id, "signtype" => 'md5', ); $arr['paysign'] = self::getsign($arr, $config['key']); return $arr; } public static function curlget($url = '', $options = array()){ $ch = curl_init($url); curl_setopt($ch, curlopt_returntransfer, 1); curl_setopt($ch, curlopt_timeout, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, curlopt_ssl_verifypeer, false); curl_setopt($ch, curlopt_ssl_verifyhost, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function curlpost($url = '', $postdata = '', $options = array()){ if (is_array($postdata)) { $postdata = http_build_query($postdata); } $ch = curl_init(); curl_setopt($ch, curlopt_url, $url); curl_setopt($ch, curlopt_returntransfer, 1); curl_setopt($ch, curlopt_post, 1); curl_setopt($ch, curlopt_postfields, $postdata); curl_setopt($ch, curlopt_timeout, 30); //设置curl允许执行的最长秒数 if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, curlopt_ssl_verifypeer, false); curl_setopt($ch, curlopt_ssl_verifyhost, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function createnoncestr($length = 16){ $chars = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789'; $str = ''; for ($i = 0; $i<$length; $i++){ $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } public static function arraytoxml($arr){ $xml = "<xml>"; foreach ($arr as $key => $val){ if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } else { $xml .= "<" . $key . "><![cdata[" . $val . "]]></" . $key . ">"; } } $xml .= "</xml>"; return $xml; } public static function getsign($params, $key){ ksort($params, sort_string); $unsignparastring = self::formatqueryparamap($params, false); $signstr = strtoupper(md5($unsignparastring . "&key=" . $key)); return $signstr; } protected static function formatqueryparamap($paramap, $urlencode = false){ $buff = ""; ksort($paramap); foreach ($paramap as $k => $v){ if (null != $v && "null" != $v) { if ($urlencode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } } $reqpar = ''; if (strlen($buff)>0) { $reqpar = substr($buff, 0, strlen($buff) - 1); } return $reqpar; }}
四:获取js-sdk的config参数
根据微信公众平台开发者文档:
所有需要使用js-sdk的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的spa的web app可在每次url变化时进行调用,目前android微信客户端不支持pushstate的h5新特性,所以使用pushstate来实现web app的页面会导致签名失败,此问题会在android6.2中修复)。
即:
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appid: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 noncestr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsapilist: [] // 必填,需要使用的js接口列表,所有js接口列表见附录2});
1.微信支付类 wechatpay.php
<?phpnamespace api\sdk;use yii;class wechatpay{ public function getsignpackage($url) { $jsapiticket = self::getjsapiticket(); $timestamp = time(); $noncestr = self::createnoncestr(); // 这里参数的顺序要按照 key 值 ascii 码升序排序 $string = "jsapi_ticket=".$jsapiticket."&noncestr=".$noncestr."×tamp=".$timestamp."&url=".$url; $signature = sha1($string); $signpackage = array( "appid" => $this->appid, "noncestr" => $noncestr, "timestamp" => $timestamp, "url" => $url, "signature" => $signature, "rawstring" => $string ); return $signpackage; } public static function getjsapiticket() { //使用redis缓存 jsapi_ticket $redis = yii::$app->redis; $redis_ticket = $redis->get('wechat:jsapi_ticket'); if ($redis_ticket) { $ticket = $redis_ticket; } else { $accesstoken = self::getaccesstoken(); $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$accesstoken; $res = json_decode(self::curlget($url)); $ticket = $res->ticket; if ($ticket) { $redis->set('wechat:jsapi_ticket', $ticket); $redis->expire('wechat:jsapi_ticket', 7000); } } return $ticket; } public static function getaccesstoken() { //使用redis缓存 access_token $redis = yii::$app->redis; $redis_token = $redis->get('wechat:access_token'); if ($redis_token) { $access_token = $redis_token; } else { $appid = yii::$app->params['wechat']['appid']; $appsecret = yii::$app->params['wechat']['appsecret']; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret; $res = json_decode(self::curlget($url)); $access_token = $res->access_token; if ($access_token) { $redis->set('wechat:access_token', $access_token); $redis->expire('wechat:access_token', 7000); } } return $access_token; } public static function curlget($url = '', $options = array()){ $ch = curl_init($url); curl_setopt($ch, curlopt_returntransfer, 1); curl_setopt($ch, curlopt_timeout, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, curlopt_ssl_verifypeer, false); curl_setopt($ch, curlopt_ssl_verifyhost, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function curlpost($url = '', $postdata = '', $options = array()){ if (is_array($postdata)) { $postdata = http_build_query($postdata); } $ch = curl_init(); curl_setopt($ch, curlopt_url, $url); curl_setopt($ch, curlopt_returntransfer, 1); curl_setopt($ch, curlopt_post, 1); curl_setopt($ch, curlopt_postfields, $postdata); curl_setopt($ch, curlopt_timeout, 30); //设置curl允许执行的最长秒数 if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, curlopt_ssl_verifypeer, false); curl_setopt($ch, curlopt_ssl_verifyhost, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function createnoncestr($length = 16){ $chars = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789'; $str = ''; for ($i = 0; $i<$length; $i++){ $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; }}
2.获取config参数接口
public function actionconfig(){ if (isset($_request['url'])) { $url = $_request['url']; //微信支付参数 $appid = yii::$app->params['wechat']['appid']; $mchid = yii::$app->params['wechat']['mchid']; $key = yii::$app->params['wechat']['key']; $wx_pay = new wechatpay($mchid, $appid, $key); $package = $wx_pay->getsignpackage($url); $result['error'] = 0; $result['msg'] = '获取成功'; $result['config'] = $package; } else { $result['error'] = 1; $result['msg'] = '参数错误'; } return $result;}
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注!
相关推荐:
如何处理yii2.0 basic代码中路由链接被转义
yii2框架实现数据库常用操作解析
以上就是关于利用yii2微信后台开发的解析的详细内容。