《PHP應用:完美利用Yii2微信后臺開發的系列總結》要點:
本文介紹了PHP應用:完美利用Yii2微信后臺開發的系列總結,希望對您有用。如果有疑問,可以聯系我們。
相關主題:YII框架
網上有很多關于YII2.0微信開發教程,但是太過復雜凌亂,所以今天在這里給大家整理總結利用Yii2微信后臺開發的系列了,給需要的小伙伴們參考.
PHP學習
一:接入微信
PHP學習
Yii2后臺配置
PHP學習
1.在app/config/params.php中配置token參數
PHP學習
return [
//微信接入
'wechat' =>[
'token' => 'your token',
],
];
2.在app/config/main.php中配置路由PHP學習
因為接口模塊使用的RESTful API,所以需要定義路由規則.
PHP學習
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'wechat',
'extraPatterns' => [
'GET valid' => 'valid',
],
],
],
],
3.在app/controllers中新建WechatController
PHP學習
<?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;
}
}
}
}
微信公眾號后臺配置
PHP學習
在微信公眾號后臺配置URL和Token,然后提交驗證即可.PHP學習
URL:http://app.demo.com/wechats/valid
Token:your token
二:獲取用戶信息
PHP學習
用戶表設計PHP學習
代碼如下:
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`);
獲取用戶信息的相關接口
PHP學習
1.用戶授權接口:獲取access_token、openId等;獲取并保存用戶資料到數據庫
PHP學習
代碼如下:
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.從微信獲取用戶資料
PHP學習
代碼如下:
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.獲取用戶資料接口PHP學習
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;
}
?PHP學習
三:微信支付
PHP學習
1.微信支付接口:打包支付數據
PHP學習
代碼如下:
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.接收微信發送的異步支付結果通知
PHP學習
代碼如下:
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學習
代碼如下:
<?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參數
PHP學習
根據微信公眾平臺開發者文檔:PHP學習
所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調用(同一個url僅需調用一次,對于變化url的SPA的web app可在每次url變化時進行調用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實現web app的頁面會導致簽名失敗,此問題會在Android6.2中修復).PHP學習
即:
PHP學習
代碼如下:
wx.config({
??? debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印.
??? appId: '', // 必填,公眾號的唯一標識
??? timestamp: , // 必填,生成簽名的時間戳
??? nonceStr: '', // 必填,生成簽名的隨機串
??? signature: '',// 必填,簽名,見附錄1
??? jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2
});
1.微信支付類 WechatPay.php
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參數接口
PHP學習
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微信后臺開發全部過程及示例代碼,希望本文對大家基于php的微信公眾平臺開發有所幫助.PHP學習
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/5625.html