>

宏观应用Yii2微信后台开拓的成千上万总计

- 编辑:至尊游戏网站 -

宏观应用Yii2微信后台开拓的成千上万总计

李秉骏:在Phonegap下实现oAuth认证

2012/07/18 · HTML5 · 2 评论 · 来源: 李秉骏     · HTML5

正文由李秉骏(@CashLee李秉骏)投稿于伯乐在线,也应接任何朋友投稿。提醒:投稿时记得留下搜狐账号哦 图片 1

近来做过一次关于Phonegap的实地沟通会议分享。基本上把Phonegap的部分风味和大家沟通了后生可畏晃,我们对此Phonegap的 兴趣也是相当多的。不过因为Phonegap相对于原生应用来说,唯有一个View,那些View正是一个Web的器皿,那使得Phonegap就存在比很多限制。当中有的的范围我们早就经过HTML5的API以致Phonegap为大家搭建的桥去实现了,别的一些大家就得经过Phonegap plugins来兑现,而实在小编个人以为Phonegap最精锐的地点也在于有那么大的四个群众体育在为他提供五颜六色的Plugins,以便去应对实在项 目中相见的难题。

自家记得在和大家调换的时候我们平常会问Phonegap如何是好地点的缓存啊(WebSQL),如何近乎原生应用(这么些关系到架构,分界面渲染难题,这 里小编也不佳深切讲,究竟不是本文要切磋的内容),还会有二个很头痛的标题正是意气风发旦要做二个开放平台的选拔,怎么样落到实处oAuth认证。此前本身也蒙受过类似的一 些意况,当自家重新碰到这些棘手的难点的时候,作者深信必定会将也可以有Phonegap的观者蒙受类似的状态的。于是自个儿就总括下来何我们商量一下怎么着缓和那几个主题材料吧。

第一目的:解决oAuth认证。

成立安排:1. 知道oAuth原理;2.领悟Phonegap在管理这么些主题素材时候的运维机制;3. 制订陈设实今世码。

上边咱们就来一步一步地分析,看怎么化解这一个状态呢。(因为自个儿在品种中境遇的是Tencent和讯开放平台的oAuth认证,那么上边笔者就用TencentoAuth认证为例吧)

关于oAuth认证,相信做过开放平台应用的相恋的人都已经特别纯熟了,借使您还未曾做过照旧对于oAuth认证流程特不打听,那么本身建议您先掌握一 下原理,在那处自身不希望花太多的字数去介绍这几个东西,因为在多数地点都足以找到,上边作者推荐八个地点方便大家去读书,必供给读书,那会对你精晓上面包车型客车稿子 有莫斯中国科学技术大学学的支援的。

Tencent博客园开放平台:

腾讯网微博开放平台:

理所必然在这里边上面需求演讲表明的是oAuth认证机制是二个通用的手段,不过因为种种开放平台有和睦的国策,因而大概在中间稍有改观,并且最终取得的权能也会各不同。而新近腾讯网新浪实在太多坑爹的事务了,实在忍受不住,于是本身转战到腾讯的阳台了。

好的,要是您看完了oAuth认证的流水生产线,就径直到那边来。功高望重,在oAuth认证的流程中,有多少个授权页面,而这些授权页面是由此开放平台提供的,具体的样式见下图:

图片 2

本条页面用于输入开放平台的帐户以至密码,通过授权获取响应的openid以致openkey,最后换取access-token(待会笔者会结合Tencent博客园oAuth认证流程的性状,以至代码和豪门解析的)。

本条页面是弹出的,如若在Phonegap里面做的话会很意外:1,因为属于弹窗,在Phonegap中笔者正是四个WebView借令你还弹的话 就能够飞到了Safari的浏览器中,那就跳出应用本人,跳出来认证还会有戏呢?2,通过iFrame,首先体验很倒霉,其次iFrame本身又属于跨域的 难点,那就不好消除了(为何体验倒霉啊,首借使因为授权页面包车型大巴体制是不定点的,类似Tencent今日头条开放平台,就比今日头条的授权页面做得差,根本不和手提式有线电电话机宽容的, 並且有个别做得好的,认证页宽度正是320px,就占了您风姿洒脱切应用的版面,体验很倒霉)那么Phonegap中该怎么着兑现呢?

带着难点,大家就愿意在Phonegap中另行引进叁个WebView。刚刚提到Phonegap的强盛还在于很三个人以至法定的集体,为其提供了风流浪漫套很好的插件机制,以缓和五颜六色的内需。在Phonegap中有八个插件叫做ChildBrowser,看名就能够猜到其意义正是:子浏览器。(其实本身在上一回的 Phonegap专项论题本事分享中以致谈到到让大家用那么些事物去消除,不过当下分享时间少于只好够草率带过,抱歉)子浏览器的功用其实正是令你在 Phonegap应用内部调起贰个浏览器的View,让您进行pdf,图片,录像,以至网页阅读的工具。(实际上你看自个儿上面的截图,就是用 ChildBrowser来完成的)那就好了,那就足以让您调起浏览器并且不跳出应用本人了,能够很好地化解oAuth认证的主题素材。 ChildBrowser下载地址:

在地方上面,你应有已经观察ChildBrowser的安装方式甚至选拔办法了,特轻巧,真正的即插即用。假如您感到荷兰语太难,那小编就帮不了你 了,你就机关谷歌翻译一下呢。相信你神速就能够做出二个ChildBrowser的德姆o的。在此个地点下边,其实你回来上意气风发层目录,其实您也 已经看见五颜六色的Phonegap Plugins,通过这么些事物,你仍为能够调用起手提式有线电话机内部越来越多有趣的能源的!那一个就要靠你和煦去开掘啦!(别的平台的运用也可能有对应的插件的Android开拓者不要骂果粉哦!)

好了日益地我们就要涉及到代码部分了。首先大家看看调用ChildBrowser的Javascript代码:

JavaScript

cb = window.plugins.childBrowser; /* if(cb != null) { cb.onLocationChange = function(loc){ root.locChanged(loc); };//地址发生改换时候实行的函数 cb.onClose = function(){root.onCloseBrowser(); };//通过js关闭ChildBrowser的措施 cb.onOpenExternal = function(){root.onOpenExternal(); }; */ cb.showWebPage("");

1
2
3
4
5
6
7
8
        cb = window.plugins.childBrowser;
/*
        if(cb != null) {
        cb.onLocationChange = function(loc){ root.locChanged(loc); };//地址发生改变时候执行的函数
        cb.onClose = function(){root.onCloseBrowser(); };//通过js关闭ChildBrowser的办法
        cb.onOpenExternal = function(){root.onOpenExternal(); };
*/
        cb.showWebPage("http://google.com");

中间cb正是开头化的ChildBrowser,而showWebPage便是调起这些页面包车型地铁秘诀。可以看到代码中要张开的网址就是Google.com啦,这几个地球人都能够看得懂了。于是大家就足以立时想到大家要用ChildBrowser张开的网站是咱们在英特网钦命的采纳授权站点 了。而自个儿是布署在SAE上边的,所以下边包车型地铁例子也用PHP来讲吧,期望语言也是同大器晚成的道理,转义就足以了。在说代码从前,大家先来讲说现实通信的流程,以及我们接下去要达到规定的规范的对象。

图片 3
在这处,大家的手提式有线电话机端是通过拜候SAE服务器,由SAE服务器管理数据并与Tencent今日头条开放平台通信的,这里手提式有线电话机端并不曾直接和Tencent天涯论坛开放平台通信(作者那样 管理的案由是1,方便在劳务器端管理帐户,那样的话能够观测自身的运用的帐户境况;2,服务器端实现推送机制,方便管理token以及做api;3,服务 器端还可以够和别的开放平台帐户绑定)。因此,我们的所有的事认证方案会在服务器端达成。

而依照腾讯新浪开放平台,大家率先会在开放平台上面注册自个儿的行使,注册的流程以致艺术自己不说了,注册的地方是:,注册你的行使后,你对号入座能够获得的事物是:

JavaScript

接纳名称:mobile_test_api 应用项目:客商端应用 App Key:88888888 App Secret:ainidenideiienfeomeomroemrome

1
2
3
4
应用名称:mobile_test_api
应用类型:客户端应用
App Key:88888888
App Secret:ainidenideiienfeomeomroemrome

在此边作者的App key甚至App Secret是假的(你懂的,你应当有你协和的),上边大家就使用Tencent提须要我们的PHP SDK,下载地址:。有了SDK后大家就足以把SDK放到本身的情形方面,然后配置服务器端的代码了。下图是本人大约安顿的服务端的代码,lib下寄存的便是Tencent新浪的sdk。当然实际生产情况和这一个有两样。这里独有作为示范使用:

图片 4

下边就根据腾讯今日头条证实的流程,逐大器晚成批注一下这个文件以致中间的代码吧。

index.php

PHP

<?php require_once 'app_config.php'; $url=" header('Location:'.$url);

1
2
3
4
5
6
<?php
require_once 'app_config.php';
 
$url="https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id=".$client_id."&APP_KEY=".$app_key."&wap=2&response_type=code&redirect_uri=http://yoururl.com/get_auth.php";//指定URL地址
 
header('Location:'.$url);

此处引入的app_config.php

PHP

<?php $client_id = '8888888888'; $app_key = 'anienineiienrieireowq2839289';

1
2
3
4
5
<?php
 
$client_id = '8888888888';
 
$app_key = 'anienineiienrieireowq2839289';

因为根据Tencent微博开放平台,大家首先步要得到的是Code,如下所述,大家要做的正是办好布置,获取这些Code

JavaScript

首先步:央浼code 央求方法: GET 央浼地址: 重返结果: 如果授权成功,授权服务器会将客户的浏览器重定向到redirect_uri,并带上code,openid和openkey等参数,重定向的url如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
第一步:请求code
 
请求方法:
GET
 
请求地址:
 
https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id=APP_KEY&amp;response_type=code&amp;redirect_uri=http://www.myurl.com/example
 
返回结果:
如果授权成功,授权服务器会将用户的浏览器重定向到redirect_uri,并带上code,openid和openkey等参数,重定向的url如下:
 
http://www.myurl.com/example?code=CODE&amp;openid=OPENID&amp;openkey=OPENKEY

切实需求哀告附带的参数,必供给不成方圆oAuth2.0鉴权的页面提醒的进展。()

然后大家再来看看大家所布署的公文:

get_auth.php

PHP

<?php require_once 'app_config.php'; $code = $_REQUEST['code']; $openid = $_REQUEST['openid']; $openkey = $_REQUEST['openkey']; $url = ""; $message = file_get_contents($url); /* success to print the access token message */ $access = explode("=",$message); print_r("<br />"); $access_message = explode("&",$access[1]); $access_token = $access_message[0]; $user_name = $access[4]; print_r($access_token ." " . $user_name);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
 
require_once 'app_config.php';
 
$code = $_REQUEST['code'];
 
$openid = $_REQUEST['openid'];
 
$openkey = $_REQUEST['openkey'];
 
$url = "https://open.t.qq.com/cgi-bin/oauth2/access_token?client_id=".$client_id."&client_secret=".$app_key."&grant_type=authorization_code&code=".$code."&redirect_uri=http://yoururl.com/get_auth.php";
 
$message = file_get_contents($url);
 
/* success to print the access token message */
 
$access = explode("=",$message);
 
print_r("<br />");
 
$access_message = explode("&",$access[1]);
 
$access_token = $access_message[0];
 
$user_name = $access[4];
 
print_r($access_token ."   " . $user_name);

实质上到上述结束,大家的配备文件已经弄好了。在这里个布局文件中,实际上大家要做的就是Tencent天涯论坛开放平新竹提起的第二步:

JavaScript

其次步:央浼accesstoken 央求地址: 重回结果: 重临字符串: access_token=ACCESS_TOKEN&expires_in=60&refresh_token=REFRESH_TOKEN

1
2
3
4
5
6
7
8
9
第二步:请求accesstoken
 
请求地址:
 
https://open.t.qq.com/cgi-bin/oauth2/access_token?client_id=APP_KEY&amp;client_secret=APP_SECRET&amp;redirect_uri=http://www.myurl.com/example&amp;grant_type=authorization_code&amp;code=CODE
 
返回结果:
返回字符串:
access_token=ACCESS_TOKEN&amp;expires_in=60&amp;refresh_token=REFRESH_TOKEN

只要你今后已经安排好您的劳务端口,已经配备好手提式有线电话机端的ChildBrowser,你就曾经得以在手提式有线电话机方面看看整个认证的流水生产线了。今后的做事风华正茂度完结了大多数了,然则稳重的敌人恐怕会发觉,对啊,认证是产生了,手提式有线话机上照旧尚未获得授权啊,因为授权后的新闻还不可见因而手提式有线电话机去赢得。不要 急,ChildBrowser有意思的地点还未有完呢。在二哥伦比亚大学端方面大家落成了oAuth认证,总有风姿洒脱对参数再次来到,不管accesstoken是还是不是存在手提式有线电话机端,你无法不有个帐户机制和服务端通信。作者的服务端在SAE上边,笔者就确立一个唯大器晚成id给手机,于是作者就建构了多个帐户机制,存在服务端上,服务端上囤积的事物是:

MySQL

CREATE TABLE IF NOT EXISTS `auth_user` ( `id` int(10) NOT NULL AUTO_INCREMENT, `muser` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `access_token` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `openid` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `openkey` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

1
2
3
4
5
6
7
8
9
10
CREATE TABLE IF NOT EXISTS `auth_user` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `muser` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `access_token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `openid` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `openkey` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

其实那么些表也还未曾周到,笔者必须还要纪录那么些顾客是还是不是在线(如若有推送机制)。此后手提式有线电话机端和服务端通信就经过地点的id以至token等的音信举办通信,再经过服务端想腾讯新浪张开api的电视发表,获取大家想要的音信。那么证明后大家因此什么样路径得到表达后重返的音讯呢?大家看看上边JS调整ChildBrowser的代码。会发觉里头有二个艺术:

JavaScript

cb.onLocationChange = function (loc){ console.warn(loc); };

1
cb.onLocationChange = function (loc){ console.warn(loc); };

借让你在xCode下面跑这段代码的话,你会发觉loc打出来的是历次ChildBrowser里面浏览的网页退换的地方。那个时候大家就足以随机应变,依照这里提供的艺术,用url的不二等秘书诀把地点再次来到到Phonegap担负逻辑管理的JS代码中,同期将有关须求通信的音信也回到。重回后还足以因而回 调的点子进行关闭ChildBrowser的代码:

JavaScript

cb.close();

1
cb.close();

当然,你还足以实行越多异步伏乞的代码。至于说还足以因而什么样的作品张开广播发表其实还会有比较多措施,小编这里仅仅是提供一下思路指导以致艺术。具体的 话,还要实践出真理论,做到那叁个安全的广播发表还值得大家继续浓烈商量。那么我要介绍的轮廓就到此地截止。因为实在项目中我们还会有push notification的建制,所以随后自己应该还大概会联同@Jeff_Kit 达成一下Phonegap的推送方案,并整治出sdk,成文后开放出来方便大家交换。

对于本文假使有何样难点依然提议都得以间接向本身陈诉,笔者的新浪知乎是:@CashLee李秉骏 ,作者还平日共享部分代码片段在github上边(开源的精力非常少,所以开源项目比较少,希望未来增添吗。)小编的Github账号, 应接您和本身每时每刻开展交换,也目的在于Phonegap的中原开荒者社区会变得进一步优良。

小心:ChildBrowser控件在实际条件中因为安全难点恐怕必要修改,通信进度中参数也建议加密。:-)

 

正文由李秉骏(@CashLee李秉骏)投稿于伯乐在线,也应接任何朋友投稿。提示:投稿时记得留下新浪账号哦 图片 5

【如需转发,请标明并保存原作链接和我等消息,多谢同盟!】

 

 

1 赞 收藏 2 评论

图片 6

英特网有不菲关于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' => 'yiirestUrlRule',
  'controller' => 'wechat',
  'extraPatterns' => [
  'GET valid' => 'valid',
  ],
 ],
 ],
],

3.在app/controllers中新建WechatController

<?php

namespace apicontrollers;

use Yii;
use yiirestActiveController;

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

}

微信公众号后台配置

在微信公众号后台配置UEnclaveL和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 = '';
    //初叶化八个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 = '';
    //开头化二个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 apisdk;
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('', 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); //设置cU凯雷德L允许推行的最长秒数
        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.第22中学期维修复)。

即:

复制代码 代码如下:

wx.config({
    debug: true, // 开启调节和测试形式,调用的具备api的归来值会在客户端alert出来,若要查看传入的参数,能够在pc端展开,参数消息会通过log打出,仅在pc端时才会打字与印刷。
    appId: '', // 必填,群众号的无可比拟标志
    timestamp: , // 必填,生成具名的光阴戳
    nonceStr: '', // 必填,生成签字的人身自由串
    signature: '',// 必填,签名,见附录1
    jsApiList: [] // 必填,须要使用的JS接口列表,全部JS接口列表见附录2
});

1.微信支付类 WechatPay.php

复制代码 代码如下:

<?php
namespace apisdk;
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 = ";
            $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 = ";
            $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); //设置cUWranglerL允许实行的最长秒数
        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微信后台开荒总体进度及示范代码,希望本文对咱们基于php的微信公众平台开荒具备助于。

你可能感兴趣的稿子:

  • Yii2 RESTful中api的运用及支出实例详解
  • Yii2中装置与收获别称的函数(set阿里as和getAlias)用法剖判
  • Yii第22中学YiiBase自动加载类、援引文件措施分析(autoload)
  • Yii2创设调控器(createController)方法详解
  • Yii2宗旨(Theme)用法详解
  • Yii2创造表单(ActiveForm)方法详解
  • Yii2验证器(Validator)用法剖判
  • yii2 RBAC使用DbManager达成后台权限判别的秘技
  • Yii2简单实现多语言配置的艺术
  • yii2调节器Controller Ajax操作示例
  • Yii2中Restful API原理实例深入分析

本文由技术教程发布,转载请注明来源:宏观应用Yii2微信后台开拓的成千上万总计