完美利用Yii2微信后臺開發(fā)的系列總結(jié)
來源:易賢網(wǎng) 閱讀:1064 次 日期:2016-08-12 14:45:59
溫馨提示:易賢網(wǎng)小編為您整理了“完美利用Yii2微信后臺開發(fā)的系列總結(jié)”,方便廣大網(wǎng)友查閱!

網(wǎng)上有很多關(guān)于YII2.0微信開發(fā)教程,但是太過復(fù)雜凌亂,所以今天在這里給大家整理總結(jié)利用Yii2微信后臺開發(fā)的系列了,給需要的小伙伴們參考。

一:接入微信

Yii2后臺配置

1.在app/config/params.php中配置token參數(shù)

return [

 //微信接入

 'wechat' =>[

 'token' => 'your token',

 ],

];

2.在app/config/main.php中配置路由

因?yàn)榻涌谀K使用的RESTful API,所以需要定義路由規(guī)則。

'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,然后提交驗(yàn)證即可。

URL:http://app.demo.com/wechats/valid

Token:your token

二:獲取用戶信息

用戶表設(shè)計(jì)

代碼如下:

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`);

獲取用戶信息的相關(guān)接口

1.用戶授權(quán)接口:獲取access_token、openId等;獲取并保存用戶資料到數(shù)據(jù)庫

代碼如下:

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';

    //初始化一個(gè)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成功,數(shù)據(jù)解析

    $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 {

        //保存用戶資料

    }

    //前端網(wǎng)頁的重定向

    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';

    //初始化一個(gè)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.微信支付接口:打包支付數(shù)據(jù)

代碼如下:

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();

        //微信支付參數(shù)

        $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'] = '請求參數(shù)錯(cuò)誤';

    }

    return $result;

}

2.接收微信發(fā)送的異步支付結(jié)果通知

代碼如下:

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);

    }

    //微信支付參數(shù)

    $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);

    //驗(yàn)證簽名

    $arr = (array)$postObj;

    unset($arr['sign']);

    if ($wx_pay->getSign($arr, $key) != $postObj->sign) {

        die("簽名錯(cuò)誤");

    }

    //支付處理正確-判斷是否已處理過支付狀態(tài)

    $orders = Order::find()->where(['uid'=>$postObj->openid, 'oid'=>$postObj->out_trade_no, 'status' => 0])->all();

    if(count($orders) > 0){

        //更新訂單狀態(tài)

        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 {

        //訂單狀態(tài)已更新,直接返回

        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請求 不驗(yàn)證證書和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); //設(shè)置cURL允許執(zhí)行的最長秒數(shù)

        if (!empty($options)) {

            curl_setopt_array($ch, $options);

        }

        //https請求 不驗(yàn)證證書和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參數(shù)

根據(jù)微信公眾平臺開發(fā)者文檔:

所有需要使用JS-SDK的頁面必須先注入配置信息,否則將無法調(diào)用(同一個(gè)url僅需調(diào)用一次,對于變化url的SPA的web app可在每次url變化時(shí)進(jìn)行調(diào)用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來實(shí)現(xiàn)web app的頁面會導(dǎo)致簽名失敗,此問題會在Android6.2中修復(fù))。

即:

代碼如下:

wx.config({

    debug: true, // 開啟調(diào)試模式,調(diào)用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會通過log打出,僅在pc端時(shí)才會打印。

    appId: '', // 必填,公眾號的唯一標(biāo)識

    timestamp: , // 必填,生成簽名的時(shí)間戳

    nonceStr: '', // 必填,生成簽名的隨機(jī)串

    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();

        // 這里參數(shù)的順序要按照 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請求 不驗(yàn)證證書和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); //設(shè)置cURL允許執(zhí)行的最長秒數(shù)

        if (!empty($options)) {

            curl_setopt_array($ch, $options);

        }

        //https請求 不驗(yàn)證證書和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參數(shù)接口

public function actionConfig(){

 if (isset($_REQUEST['url'])) {

 $url = $_REQUEST['url'];

 //微信支付參數(shù)

 $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'] = '參數(shù)錯(cuò)誤';

 }

 return $result;

}

以上就是利用Yii2微信后臺開發(fā)全部過程及示例代碼,希望本文對大家基于php的微信公眾平臺開發(fā)有所幫助。

更多信息請查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:完美利用Yii2微信后臺開發(fā)的系列總結(jié)
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65317125(9:00—18:00) 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)