本文内容较多,包括微信接入、获取微信用户信息、微信支付、JSSDK配置参数获取等部分。如果读者对微信开发没有一个主观上的认识,那么建议读者先研读 微信公众平台开发者文档 ,然后再阅读本文,效果更佳!另外本文的分章节版本可以在 八宝粥的博客 找到。
接入微信
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
<?php namespace 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/valid Token: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
<?php namespace 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
<?php namespace 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实现微信公众号后台开发的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

记事本++7.3.1
好用且免费的代码编辑器