转自 方倍工作室微信公众平台开发

LNMP的配置与优化

一、LNMP的下载

LNMP一键安装包是一个用Linux Shell编写的可以为CentOS/RadHat/Fedora、Debian/Ubuntu/Raspbian/Deepin VPS或独立主机安装LNMP(Nginx/MySQL/PHP)、LNMPA(Nginx/MySQL/PHP/Apache)、LAMP(Apache/MySQL/PHP)生产环境的Shell程序。同时提供一些实用的辅助工具如:虚拟主机管理、FTP用户管理、Nginx、MySQL/MariaDB、PHP的升级、常用缓存组件Redis、Xcache等的安装、重置MySQL root密码、502自动重启、日志切割、SSH防护DenyHosts/Fail2Ban、备份等许多实用脚本。

官方网站为 https://www.lnmp.org/

最新稳定版本: LNMP 1.3

完整版:http://soft.vpser.net/lnmp/lnmp1.3-full.tar.gz (478MB)

 

二、常用配置

1. 启用PATH_INFO支持

该功能用于ThinkPHP开发

网站配置目录 ./usr/local/nginx/conf/vhost/www.fangbei.org.conf

打开并添加如下红包部分

复制代码

server
    {
        listen 80;
        #listen [::]:80;
        server_name www.fangbei.org;
        index index.html index.htm index.php default.html default.htm default.php;
        root  /home/wwwroot/www.fangbei.org;

        include other.conf;
        #error_page   404   /404.html;
        include enable-php.conf;

        location / {
            if (!-e $request_filename){
                rewrite ^/(.*)$ /index.php?s=/$1 last;
            }
        }
        
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }

        location ~ .*\.(js|css)?$
        {
            expires      12h;
        }

        location ~ /\.
        {
            deny all;
        }
        
        access_log off;
    }

复制代码

 

2. 禁用mysql日志

在MySQL数据库中,mysql-bin.000001、mysql- bin.000002等文件是数据库的操作日志,例如UPDATE一个表,或者DELETE一些数据,即使该语句没有匹配的数据,这个命令也会存储到日志文件中,还包括每个语句执行的时间,也会记录进去的。

比如如下

复制代码

[root@www.fangbei.org /]# cd /usr/local/mysql/var/
[root@www.fangbei.org var]# ll
total 29964
drwx------ 2 mysql mysql     4096 Feb 21 17:42 100893722
-rw-r----- 1 mysql root      8477 Feb 21 18:41 www.fangbei.org.err
-rw-rw---- 1 mysql mysql        5 Feb 21 18:41 www.fangbei.org.pid
-rw-rw---- 1 mysql mysql 18874368 Feb 21 18:41 ibdata1
-rw-rw---- 1 mysql mysql  5242880 Feb 21 18:41 ib_logfile0
-rw-rw---- 1 mysql mysql  5242880 Feb 21 17:08 ib_logfile1
drwx------ 2 mysql mysql     4096 Feb 21 17:08 mysql
-rw-rw---- 1 mysql mysql    27735 Feb 21 17:08 mysql-bin.000001
-rw-rw---- 1 mysql mysql  1113246 Feb 21 17:08 mysql-bin.000002
-rw-rw---- 1 mysql mysql      264 Feb 21 17:08 mysql-bin.000003
-rw-rw---- 1 mysql mysql     1119 Feb 21 17:08 mysql-bin.000004
-rw-rw---- 1 mysql mysql      126 Feb 21 17:08 mysql-bin.000005
-rw-rw---- 1 mysql mysql   127076 Feb 21 18:41 mysql-bin.000006
-rw-rw---- 1 mysql mysql      107 Feb 21 18:41 mysql-bin.000007
-rw-rw---- 1 mysql mysql      133 Feb 21 18:41 mysql-bin.index
drwx------ 2 mysql mysql     4096 Feb 21 17:08 performance_schema
[root@www.fangbei.org var]# 

复制代码

以及

复制代码

[root@www.fangbei.org var]# cd /root
[root@www.fangbei.org ~]# ll
total 491064
drwxr-xr-x 4 mysql mysql      4096 Feb 21 16:44 databases_backup_20170221164407
drwxr-xr-x 7 root  root       4096 May 27  2016 lnmp1.3-full
-rw-r--r-- 1 root  root  500932095 Dec  4 12:32 lnmp1.3-full.tar.gz
-rw-r--r-- 1 root  root    1898084 Feb 21 17:18 lnmp-install.log
[root@www.fangbei.org ~]# cd databases_backup_20170221164407/
[root@www.fangbei.org databases_backup_20170221164407]# ll
total 21284
drwx------ 2 mysql mysql     4096 Feb 21 16:38 100893722
-rw-r----- 1 mysql root      4654 Feb 21 16:44 www.fangbei.org.err
-rw-rw---- 1 mysql mysql 10485760 Feb 21 16:44 ibdata1
-rw-rw---- 1 mysql mysql  5242880 Feb 21 16:44 ib_logfile0
-rw-rw---- 1 mysql mysql  5242880 Feb 21 16:02 ib_logfile1
drwx------ 2 mysql mysql     4096 Feb 21 16:02 mysql
-rw-rw---- 1 mysql mysql    19758 Feb 21 16:02 mysql-bin.000001
-rw-rw---- 1 mysql mysql   765307 Feb 21 16:02 mysql-bin.000002
-rw-rw---- 1 mysql mysql      263 Feb 21 16:02 mysql-bin.000003
-rw-rw---- 1 mysql mysql      731 Feb 21 16:02 mysql-bin.000004
-rw-rw---- 1 mysql mysql      125 Feb 21 16:02 mysql-bin.000005
-rw-rw---- 1 mysql mysql      497 Feb 21 16:44 mysql-bin.000006
-rw-rw---- 1 mysql mysql      114 Feb 21 16:11 mysql-bin.index
[root@www.fangbei.org databases_backup_20170221164407]# 

复制代码

这些文件的生长速度是很快的,特别占用服务器资源。当服务器资源不够充足的情况下,我们可以选择定期删除这些日志文件,或者修改配置文件,不让日志生成。

编辑my.cnf 文件,命令:vi /etc/my.cnf
注释掉 log-bin=mysql-bin 这个属性

复制代码

#skip-networking
max_connections = 500
max_connect_errors = 100
open_files_limit = 65535

# log-bin=mysql-bin
binlog_format=mixed
server-id    = 1
expire_logs_days = 10

复制代码

然后删除上述日志文件

最后重启 lnmp restart

 

3. 删除.user.ini文件

LNMP 1.2开始PHP防跨目录限制使用.user.ini,该文件在网站根目录下,可以修改open_basedir的值来设置限制目录的访问。
.user.ini文件无法直接修改,而且是隐藏文件可能在winscp下可能无法看到。

当网站被删除的时候,.user.ini可以用以下方法删除

[root@www.fangbei.org]# chattr -i ".user.ini"
[root@www.fangbei.org]# chmod 777 ".user.ini"
[root@www.fangbei.org]# rm ".user.ini"

 

作者:txw1958 发表于 2017/02/21 19:08:29 原文链接 https://blog.csdn.net/txw1958/article/details/56292797

阅读:611

 
[原]微信公众平台开发(121) 微信二维码海报

关键字:微信公众平台 二维码 海报
作者:方倍工作室
原文: http://www.cnblogs.com/txw1958/p/weixin-poster.html 

 

本文介绍微信公众平台下二维码海报的开发过程。

一、微信二维码海报介绍

微信二维码海报是指在海报中嵌入和微信用户关联的参数二维码的海报,用户分享推广之后,新用户可以被统计为被推广人员数,从而达到增加粉丝的传播效果。其使用场景如下:

 

 

二、开发流程

在微信二维码海报生成中,需要用到以下信息

1. 自定义菜单中设置一个菜单项,点击后返回二维码海报给用户

2. 接口接收到菜单点击之后,获取用户的头像、ID(可以使用OpenID)

3. 生成和用户关联的参数二维码,

4. 将参数二维码进行缩放

5. 将头像和参数二维码合并成新的参数二维码图片

6. 将新参数二维码图片做为水印合成到背景海报中

7. 将用户昵称,以及二维码时间戳(类型为临时二维码时)等文字合成到背景海报中

8. 将海报上传成临时图片素材

9. 将图片素材使用客服接口发送给用户。

 

三、微信素材准备

海报底图如下

3.1 生成自定义菜单

菜单的生成方法,请参考《微信公众平台开发(58)自定义菜单》以及方倍工作室的书籍《微信公众平台开发最佳实践(第2版)

本项目中使用的菜单JSON为

3.2 获取用户基本信息

使用方倍工作室SDK获取用户基本信息的方法如下

复制代码

    //获取用户信息
    $userinfo = $weixin->get_user_info($openid);
    var_dump($userinfo);
    
    //获取用户头像 64像素
    $headimgurl = substr($userinfo['headimgurl'],0,strripos($userinfo['headimgurl'], "/"))."/64";
    var_dump($headimgurl);
    // $headimgurl = "http://wx.qlogo.cn/mmopen/R9V6295VOlibNsicszoREqUF2CiaY8hL5fFt0D8DykUCjJ8ia4rQicbYViax3A2V0am2oUEWvw5awGia0tmwQEbI0tAu4kkCL7Eiaeia7/64";
    

复制代码

需要注意的是,用户默认头像是640像素的大图,将其切换成64位像素大小,以便放置在二维码中间。

同样的,用户基本信息的获取方法,请参考《微信公众平台开发(76) 获取用户基本信息 》以及方倍工作室的书籍《微信公众平台开发最佳实践(第2版)

用户头像信息如下所示

 

3.3 生成参数二维码

使用方倍工作室SDK获取用户基本信息的方法如下

复制代码

  //创建永久二维码,参数为用户openid
    $qrcodeinfo = $weixin->create_qrcode("QR_LIMIT_STR_SCENE", $openid);
    var_dump($qrcodeinfo);
    $qrcodeurl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=".urlencode($qrcodeinfo["ticket"]);
    var_dump($qrcodeurl);
    // $qrcodeurl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQHf7zoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL05rUGlyTXJsd2hxN3BCUnFNbTlNAAIEu1X8VwMEAAAAAA%3D%3D";

复制代码

参数二维码可以考虑使用永久字符串的,也可以考虑使用临时数字,临时数字优点没有上限限制,缺点是有有效期。永久的则相反。

同样的,参数二维码的获取方法,请参考《微信公众平台开发(83) 生成带参数二维码》以及方倍工作室的书籍《微信公众平台开发最佳实践(第2版)

参数二维码如下所示

 

 

四、微信二维码海报生成

4.1 二维码缩放

 微信二维码默认是430像素,将其缩放成300像素,核心代码如下

imagecopyresampled($qrcode_thumb, $qrcode_source, 0, 0, 0, 0, 300, 300, 430, 430);

 

4.2 头像合成到二维码图片上

核心代码如下

imagecopy($qrcode_thumb, $head_source, 118, 118, 0, 0, 64, 64);

合成后,效果如下

4.3 二维码合成到海报中

核心代码如下

//加水印
    imagecopy($dst_qr, $qrcode_thumb, 212, 410, 0, 0, 300, 300);    //水印位置

 

4.4 文字合成到海报中

核心代码如下

imagettftext($dst_qr, 30, 0, 40, 85, $textcolor, $font, $text);

合成后效果如下

 

五、素材上传与发送

5.1 上传临时图片素材

使用方倍工作室SDK上传图片素材的方法如下

复制代码

//将图片上传临时图文素材
    $material = $weixin->upload_temporary_material("image", $filename); //logo.jpg须放于类同目录,注意路径
    var_dump($material);
    $mediaid = $material["media_id"];

    // array(3) { ["type"]=> string(5) "image" ["media_id"]=> string(64) "21Lz-eMFoSsA_R5gLOUJOqxbGw6YEEPRQq-UjHVbU6q64VyUBUqt7B8252ySPKdt" ["created_at"]=> int(1487213817) }

复制代码

上传后,获得图片的media_id

 

5.2 使用客服接口发送图片

使用方倍工作室SDK发送图片的方法如下

    //客服接口发送临时图片素材
    $send_result = $weixin->send_custom_message($openid, "image", array('media_id'=>$mediaid));
    var_dump($send_result);

 

六、演示

关注方倍工作室微信公众账号,点击菜单“我的海报”

 

 

六、源码

联系QQ 1354386063

作者:txw1958 发表于 2017/02/17 11:05:05 原文链接 https://blog.csdn.net/txw1958/article/details/55505781

阅读:2512 评论:1 查看评论

 
[转]微信小程序(应用号)资源汇总整理

 

原文:http://www.cnblogs.com/txw1958/p/wechat-app-summarizing.html

 

微信小应用资源汇总整理

开源项目

文档

教程

知乎讨论

媒体报道

文章

 

其他

 公众平台小程序文档和工具
http://dwz.cn/4dH0ga

WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。
https://weui.io/?from=singlemessage&isappinstalled=0

开发微信小程序入门前
http://lattecake.com/post/20098

微信小程序资源汇总整理
http://dwz.cn/4dH6ew

全球首个微信应用号开发教程!通宵吐血赶稿。
http://dwz.cn/4dH5rd

简易教程做的页面,让更多人看到小程序后台。
http://wx.chiki.org/?from=singlemessage&isappinstalled=0

微信小程序内测版- 开发工具与文档
http://yaosimin.com/477.html?from=singlemessage&isappinstalled=0

知友陈宇强的回答
http://dwz.cn/4dH7ze

微信小程序设计规范(优化版)抢先看了!
http://dwz.cn/4dH8wb

微信小程序,制作工具解析
http://dwz.cn/4dH9gn

前端开发学习资源教程
http://dwz.cn/4dH9Ry

微信小程序视频教程链接:
https://pan.baidu.com/s/1o8cuiG6 密码: v1vt

为什么我们需要一个兼容「微信小程序」的Web框架?(内含三个超链接)
http://dwz.cn/4ekUaS

官方教程
http://dwz.cn/4eA0X8

开发资源汇总
http://dwz.cn/4eNQhO

微信小程序前端学习资源教程
http://dwz.cn/4f0VZf

微信移动UI设计规范
http://gold.xitu.io/entry/57e9cbc5a0bb9f0058560585?from=timeline&isappinstalled=0

集体学习第一课(1,2,3,4节内容)
http://dwz.cn/4ekX7c 

作者:txw1958 发表于 2016/10/08 10:32:16 原文链接 https://blog.csdn.net/txw1958/article/details/52754533

阅读:2825

 
[转]微信公众平台应用号开发教程

 

关键字:微信 应用号 开发教程
原文: http://www.cnblogs.com/txw1958/p/weixin-yingyonghao.html

本文介绍微信应用号开发过程。

目前还处于内测阶段,微信只邀请了部分企业参与封测。想必大家都关心应用号的最终形态到底是什么样子?怎样将一个「服务号」改造成为「小程序」?

我们暂时以一款简单的第三方工具的实例,来演示一下开发过程吧——

 

序言

开始开发应用号之前,先看看官方公布的「小程序」教程吧!(以下内容来自微信官方公布的「小程序」开发指南)

本文档将带你一步步创建完成一个微信小程序,并可以在手机上体验该小程序的实际效果。这个小程序的首页将会显示欢迎语以及当前用户的微信头像,点击头像,可以在新开的页面中查看当前小程序的启动日志。

1. 获取微信小程序的 AppID

首先,我们需要拥有一个帐号,如果你能看到该文档,我们应当已经邀请并为你创建好一个帐号。注意不可直接使用服务号或订阅号的 AppID。 利用提供的帐号,登录 https://mp.weixin.qq.com ,就可以在网站的「设置」-「开发者设置」中,查看到微信小程序的 AppID 了。

 微信应用号

注意:如果我们不是用注册时绑定的管理员微信号,在手机上体验该小程序。那么我们还需要操作「绑定开发者」。即在「用户身份 - 开发者」模块,绑定上需要体验该小程序的微信号。本教程默认注册帐号、体验都是使用管理员微信号。

 

2. 创建项目

我们需要通过开发者工具,来完成小程序创建和代码编辑。

开发者工具安装完成后,打开并使用微信扫码登录。选择创建「项目」,填入上文获取到的 AppID,设置一个本地项目的名称(非小程序名称),比如「我的第一个项目」,并选择一个本地的文件夹作为代码存储的目录,点击「新建项目」就可以了。

为方便初学者了解微信小程序的基本代码结构,在创建过程中,如果选择的本地文件夹是个空文件夹,开发者工具会提示,是否需要创建一个 quick start 项目。选择「是」,开发者工具会帮助我们在开发目录里生成一个简单的 demo。

微信应用号

项目创建成功后,我们就可以点击该项目,进入并看到完整的开发者工具界面,点击左侧导航,在「编辑」里可以查看和编辑我们的代码,在「调试」里可以测试代码并模拟小程序在微信客户端效果,在「项目」里可以发送到手机里预览实际效果。

 

3. 编写代码

点击开发者工具左侧导航的「编辑」,我们可以看到这个项目,已经初始化并包含了一些简单的代码文件。最关键也是必不可少的,是 app.js、app.json、app.wxss 这三个。其中,.js 后缀的是脚本文件,.json 后缀的文件是配置文件,.wxss 后缀的是样式表文件。微信小程序会读取这些文件,并生成小程序实例。

下面我们简单了解这三个文件的功能,方便修改以及从头开发自己的微信小程序。

app.js 是小程序的脚本代码。我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。调用 MINA 提供的丰富的 API,如本例的同步存储及同步读取本地数据。

微信应用号

app.json 是对整个小程序的全局配置。我们可以在这个文件中配置小程序是由哪些页面组成,配置小程序的窗口  背景色,配置导航条样式,配置默认标题。注意该文件不可添加任何注释。

微信应用号

app.wxss 是整个小程序的公共样式表。我们可以在页面组件的 class 属性上直接使用 app.wxss 中声明的样式规则。

微信应用号

 

3. 创建页面

在这个教程里,我们有两个页面,index 页面和 logs 页面,即欢迎页和小程序启动日志的展示页,他们都在 pages 目录下。微信小程序中的每一个页面的【路径 + 页面名】都需要写在 app.json 的 pages 中,且 pages 中的第一个页面是小程序的首页。

每一个小程序页面是由同路径下同名的四个不同后缀文件的组成,如:index.js、index.wxml、index.wxss、index.json。.js 后缀的文件是脚本文件,.json 后缀的文件是配置文件,.wxss 后缀的是样式表文件,.wxml 后缀的文件是页面结构文件。

index.wxml 是页面的结构文件:

微信应用号

本例中使用了 <view/>、<image/>、<text/> 来搭建页面结构,绑定数据和交互处理函数。

index.js 是页面的脚本文件,在这个文件中我们可以监听并处理页面的生命周期函数、获取小程序实例,声明并处理数据,响应页面交互事件等。

微信应用号

index.wxss 是页面的样式表:

微信应用号

页面的样式表是非必要的。当有页面样式表时,页面的样式表中的样式规则会层叠覆盖 app.wxss 中的样式规则。如果不指定页面的样式表,也可以在页面的结构文件中直接使用 app.wxss 中指定的样式规则。

index.json 是页面的配置文件:

页面的配置文件是非必要的。当有页面的配置文件时,配置项在该页面会覆盖 app.json 的 window 中相同的配置项。如果没有指定的页面配置文件,则在该页面直接使用 app.json 中的默认配置。

logs 的页面结构

微信应用号

logs 页面使用 <block/> 控制标签来组织代码,在 <block/> 上使用 wx:for-items 绑定 logs 数据,并将 logs 数据循环展开节点

微信应用号

运行结果如下:

微信应用号

 

4. 手机预览

开发者工具左侧菜单栏选择「项目」,点击「预览」,扫码后即可在微信客户端中体验。

目前,预览和上传功能尚无法实现,需要等待微信官方的下一步更新。

 

如你所见,微信官方给出的开发指南还非常简单,很多细节、代码和功能都没有明确的展示,所以接下来就到博卡君展示实力的时候啦!开发教程正式开始!

第一章:准备工作

做好准备工作很重要。开发一个微信应用号,你需要提前到微信的官方网站(weixin.qq.com)下载开发者工具。

1. 下载最新微信开发者工具,打开后你会看到该界面:

微信应用号

2. 点击「新建 web+」项目,随后出现如下画面:

微信应用号

3. 该页面内的各项内容需要注意——

  • AppID:依照官方解释来填。

  • Appname: 项目最外层文件夹名称,如你将其命名为「ABC」,则之后的全部项目内容均将保存在「/ABC/…」目录下。

  • 本地开发目录:项目存放在本地的目录。

注:再次强调,如果你和团队成员共同开发该项目,则建议你们使用同样的目录名称及本地目录,以确保协同开发的统一性。如果你之前已有项目,则导入过程与以上内容近似,不再赘述。

4. 准备工作全部完成后,点击「新建项目」按钮,弹出框点「确定」。

微信应用号

5. 如上图所示,此刻,微信开发者工具已经为你自动构建了一个初始的 demo 项目,该项目内包含了一个微信应用项目所需具备的基本内容和框架结构。点击项目名称(图中即「cards」)进入该项目,就能看到整个项目的基本架构了:

微信应用号

 

第二章:项目构架

微信目前用户群体非常庞大,微信推出公众号以后,火爆程度大家都看得到,也同样推动着 h5 的高速发展,随着公众号业务的需求越来越复杂,应用号现在的到来也是恰到好处。我们团队具体看了一两次文档后发现,它提供给开发者的方式也在发生全面的改变,从操作 DOM 转为操作数据,基于微信提供的一个过桥工具实现很多 h5 在公众号很难实现的功能,有点类似于 hybrid 开发,不同于 hybrid 开发的方式是:微信开放的接口更为严谨,结构必须采用他提供给我们的组件,外部的框架和插件都不能在这里使用上,让开发者完全脱离操作 DOM,开发思想转变很大。

工欲善其事,必先利其器。理解它的核心功能非常重要,先了解它的整个运作流程。

 

生命周期:

在index.js里面:

微信应用号

开发者工具上 Console 可以看到:

 微信应用号

 

在首页 console 可以看出顺序是 App Launch-->App Show-->onload-->onShow-->onReady。

首先是整个 app 的启动与显示,app 的启动在 app.js 里面可以配置,其次再进入到各个页面的加载显示等等。

可以想象到这里可以处理很多东西了,如加载框之类的都可以实现等等。

路由:

路由在项目开发中一直是个核心点,在这里其实微信对路由的介绍很少,可见微信在路由方面经过很好的封装,也提供三个跳转方法。

wx.navigateTo(OBJECT):保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面。

wx.redirectTo(OBJECT):关闭当前页面,跳转到应用内的某个页面。

wx.navigateBack():关闭当前页面,回退前一页面。

这三个基本上使用足够,在路由方面微信封装的很好,开发者根本不用去配置路由,往往很多框架在路由方面配置很繁琐。

组件:

此次微信在组件提供方面也是非常全面,基本上满足项目需求,故而开发速度非常快,开发前可以认真浏览几次,开发效率会很好。

其它:

任何外部框架以及插件基本上无法使用,就算原生的 js 插件也很难使用,因为以前我们的 js 插件也基本上全部是一操作 dom 的形式存在,而微信应用号此次的架构是不允许操作任何 dom,就连以前我们习惯使用的动态设置的rem.js也是不支持的。

此次微信还提供了 WebSocket,就可以直接利用它做聊天,可以开发的空间非常大。

跟公众号对比我们发现,开发应用号组件化,结构化,多样化。新大陆总是充满着惊喜,更多的彩蛋等着大家来发现。

接下来开始搞一些简单的代码了!

1. 找到项目文件夹,导入你的编辑器里面。在这里,我使用了 Sublime Text 编辑器。你可以根据自己的开发习惯选择自己喜欢的编辑器。

微信应用号

2. 接下来,你需要根据自己的项目内容调整项目结构。在范例项目中,「card_course」目录下面主要包含了「tabBar」页面以及该应用的一些配置文件。

3. 示例项目的「tabBar」是五个菜单按钮:

微信应用号

4. 找到「app.json」文件,用来配置这个五个菜单。在代码行中找到「”tabBar”」:

微信应用号

你可以根据实际项目需求更改,其中:

  • 「Color」是底部字体颜色,「selectedColor」是切换到该页面高亮颜色,「borderStyle」是切换菜单上面的一条线的颜色,「backgroundColor」是底部菜单栏背景颜色。文字描述较为抽象,建议你一一调试并查看其效果,加深印象。

  • 「“list”」下的代码顺序必须依次放置,不能随便更改。

  • 「”pagePath”」之后的文件名内,「.wxml」后缀被隐藏起来了,这是微信开发代码中人性化的一点——帮你节约写代码的时间,无须频繁声明文件后缀。

  • 「”iconPath”」为未获得显示页面的图标路径,这两个路径可以直接是网络图标。

  • 「”selectedIconPath”」为当前显示页面高亮图标路径,可以去掉,去掉之后会默认显示为「”iconPath”」的图标。

  • 「”Text”」为页面标题,也可以去掉,去掉之后纯显示图标,如只去掉其中一个,该位置会被占用。

注意:微信的底部菜单最多支持五栏(五个 icons),所以在你设计微信应用的 UI 和基本架构时就要预先考虑好菜单栏的排布。

5. 根据以上代码规则,我做好了示例项目的基本架构,供你参考:

微信应用号

微信应用号

 

6. 「Json」文件配置好后,「card_course」的基本结构入上图所示,不需要的子集都可以暂时删除,缺少的子集则需要你主动新建。删除子集时记得顺带检查一下「app.json」里的相关内容是否已经一并删除。

注意:我个人建议新建一个「wxml」文件的同时,把对应的「js」和「wxss」文件一起新建好,因为微信应用号的配置特点就是解析到一个「wxml」文件时,会同时在同级目录下找到同文件名的「js」和「wxss」文件,所以「js」文件需及时在「app.json」里预先配置好。

编写「wxml」时,根据微信应用号提供的接口编码即可,大部分就是以前的「div」,而我们现在就用「view」即可。需要用其它子集时,可以根据微信提供的接口酌情选择。

使用「class」名来设置样式,「id」名在这里基本没有什么用处。主要操作数据,不操作「dom」。

微信应用号

 

7. 以上是示例项目首页的「wxml」编码。从图中就可以看出,实现一个页面代码量非常少。

8. 「Wxss」文件是引入的样式文件,你也可以直接在里面写样式,示例中采用的是引入方式:

 微信应用号

9. 修改代码后刷新一次,可以看到未设背景的「view」标签直接变成了粉色。

注意:修改「wxml」和「wxss」下的内容后,直接 F5 刷新就能直接看到效果,修改「js」则需点击重启按钮才能看到效果。

10. 另外,公共样式可以在「app.wxss」里直接引用。

微信应用号

 微信应用号

11. 「Js」文件需要在「app.json」文件的「”page”」里预先配置好。为了项目结构清晰化,我在示例项目中的「index」首页同级目录新建其它四个页面文件,具体如下:

 微信应用号

经过以上步骤,案例中的五个底部菜单就全部配置完毕了。

 

作者:txw1958 发表于 2016/09/22 20:29:06 原文链接 https://blog.csdn.net/txw1958/article/details/52626970

阅读:1374

 
[原]网站统计功能的设计与实现

 

本文简要介绍网站统计功能的设计与实现。

本文分为以下五个部分:

  1. 埋点设计与实现
  2. 页面引入
  3. 数据接收
  4. 数据入库
  5. 统计分析

 

一、埋点设计与实现

在JavaScript中,包含了很多对象,可以用于获取用户的数据。比如Document对象用于分析每个载入浏览器的 HTML 文档,可以获得当前文档的域名、URL、及当前文档的标题;Navigator对象包含有关浏览器的信息,可以得到运行浏览器的userAgent的值,当前系统的语言;而Screen对象则可以获得当前屏幕的相关信息。通过这些对象,我们可以得到一个相当完备的用户信息。
另外,通过其他接口,还可以得到用户的mac地址及IP地址,继而可以分析出用户的机器及所在省市区地址等。

我们使用javascript获取访问信息,将统计代码伪装成图片通过浏览器访问触发,代码实现如下。

 

二、页面引入

在要做统计的web页面中引入统计脚本,并主动将其他接口获得的mac及ip地址另外传入,一个简易的页面设计如下代码所示。

 

三、数据接收

在后台接口中接收上报上来的数据。我们使用php程序获取get及post的数据来接收。

上述接口程序获得的文件日志中数据如下所示。

复制代码

17:38:25 http://www.fangbei.org?domain=www.fangbei.org&url=http%3A%2F%2Fwww.fangbei.org%2F_test%2Fstat.html&title=%e6%96%b9%e5%80%8d%e5%b7%a5%e4%bd%9c%e5%ae%a4&referrer=&sh=1920&sw=1080&cd=24&useragent=Mozilla%2F5.0%20(Linux%3B%20U%3B%20Android%205.1.1%3B%20zh-cn%3B%20Mi-4c%20Build%2FLMY47V)%20AppleWebKit%2F533.1%20(KHTML%2C%20like%20Gecko)Version%2F4.0%20MQQBrowser%2F5.4%20TBS%2F025483%20Mobile%20Safari%2F533.1%20MicroMessenger%2F6.3.9.48_refecd3e.700%20NetType%2FWIFI%20Language%2Fzh_CN&platform=Linux%20aarch64&language=zh-CN&usermac=185E0F88F5EF&apmac=185E0F88F5F0
17:38:25 
17:38:25 _GET: Key: domain; Value: www.fangbei.org
17:38:25 _GET: Key: url; Value: http://www.fangbei.org/_test/stat.html
17:38:25 _GET: Key: title; Value: 方倍工作室
17:38:25 _GET: Key: referrer; Value: 
17:38:25 _GET: Key: sh; Value: 1920
17:38:25 _GET: Key: sw; Value: 1080
17:38:25 _GET: Key: cd; Value: 24
17:38:25 _GET: Key: useragent; Value: Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; Mi-4c Build/LMY47V) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025483 Mobile Safari/533.1 MicroMessenger/6.3.9.48_refecd3e.700 NetType/WIFI Language/zh_CN
17:38:25 _GET: Key: platform; Value: Linux aarch64
17:38:25 _GET: Key: language; Value: zh-CN
17:38:25 _GET: Key: usermac; Value: 185E0F88F5EF
17:38:25 _GET: Key: apmac; Value: 185E0F88F5F0
17:38:43 http://www.fangbei.org?domain=www.fangbei.org&url=http%3A%2F%2Fwww.fangbei.org%2F_test%2Fstat.html&title=%e6%96%b9%e5%80%8d%e5%b7%a5%e4%bd%9c%e5%ae%a4&referrer=&sh=1184&sw=720&cd=24&useragent=Mozilla%2F5.0%20(Linux%3B%20U%3B%20Android%204.4.2%3B%20zh-cn%3B%20H60-L01%20Build%2FHDH60-L01)%20AppleWebKit%2F533.1%20(KHTML%2C%20like%20Gecko)Version%2F4.0%20MQQBrowser%2F5.4%20TBS%2F025489%20Mobile%20Safari%2F533.1%20MicroMessenger%2F6.3.9.48_refecd3e.700%20NetType%2FWIFI%20Language%2Fzh_CN&platform=Linux%20armv7l&language=zh-CN&usermac=185E0F88F5EF&apmac=185E0F88F5F0
17:38:43 
17:38:43 _GET: Key: domain; Value: www.fangbei.org
17:38:43 _GET: Key: url; Value: http://www.fangbei.org/_test/stat.html
17:38:43 _GET: Key: title; Value: 方倍工作室
17:38:43 _GET: Key: referrer; Value: 
17:38:43 _GET: Key: sh; Value: 1184
17:38:43 _GET: Key: sw; Value: 720
17:38:43 _GET: Key: cd; Value: 24
17:38:43 _GET: Key: useragent; Value: Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; H60-L01 Build/HDH60-L01) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.4 TBS/025489 Mobile Safari/533.1 MicroMessenger/6.3.9.48_refecd3e.700 NetType/WIFI Language/zh_CN
17:38:43 _GET: Key: platform; Value: Linux armv7l
17:38:43 _GET: Key: language; Value: zh-CN
17:38:43 _GET: Key: usermac; Value: 185E0F88F5EF
17:38:43 _GET: Key: apmac; Value: 185E0F88F5F0
17:38:50 http://www.fangbei.org?domain=www.fangbei.org&url=http%3A%2F%2Fwww.fangbei.org%2F_test%2Fstat.html&title=%e6%96%b9%e5%80%8d%e5%b7%a5%e4%bd%9c%e5%ae%a4&referrer=&sh=592&sw=360&cd=32&useragent=Mozilla%2F5.0%20(Linux%3B%20Android%204.4.2%3B%20H60-L01%20Build%2FHDH60-L01)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Version%2F4.0%20Chrome%2F30.0.0.0%20Mobile%20Safari%2F537.36&platform=Linux%20armv7l&language=zh-CN&usermac=185E0F88F5EF&apmac=185E0F88F5F0
17:38:50 
17:38:50 _GET: Key: domain; Value: www.fangbei.org
17:38:50 _GET: Key: url; Value: http://www.fangbei.org/_test/stat.html
17:38:50 _GET: Key: title; Value: 方倍工作室
17:38:50 _GET: Key: referrer; Value: 
17:38:50 _GET: Key: sh; Value: 592
17:38:50 _GET: Key: sw; Value: 360
17:38:50 _GET: Key: cd; Value: 32
17:38:50 _GET: Key: useragent; Value: Mozilla/5.0 (Linux; Android 4.4.2; H60-L01 Build/HDH60-L01) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
17:38:50 _GET: Key: platform; Value: Linux armv7l
17:38:50 _GET: Key: language; Value: zh-CN
17:38:50 _GET: Key: usermac; Value: 185E0F88F5EF
17:38:50 _GET: Key: apmac; Value: 185E0F88F5F0

 

复制代码

 

四、数据入库

要做统计分析,最终数据都要放放数据库,

数据库表设计如下

入库后如下所示

 

五、统计分析

最后,将获得的数据进行分析

比如昨天访问量的SQL查询语句如下

生成的图形如下

 

其他生成的统计图表如下

 

 

基于访问次数的二次分析-客户忠诚度的统计如下

作者:txw1958 发表于 2016/09/04 11:29:16 原文链接 https://blog.csdn.net/txw1958/article/details/52431364

阅读:961

 
[原]支付宝支付开发—当面付条码支付和扫码支付

关键字:支付宝 当面付 条码支付 扫码支付 二维码支付 订单查询 退款
作者:方倍工作室
 

本文介绍支付宝中当面付下属的条码支付、扫码支付、订单查询、退款申请的集成开发过程。

 

本文分为以下五个部分:

  1. 条码支付和扫码支付介绍
  2. 申请应用
  3. 密钥生成及配置
  4. API及SDK集成
  5. 条码支付、扫码支付、订单查询、退款申请

 

一、条码支付及二维码支付介绍

1. 条码支付

条码支付是支付宝给到线下传统行业的一种收款方式。商家使用扫码枪等条码识别设备扫描用户支付宝钱包上的条码/二维码,完成收款。用户仅需出示付款码,所有收款操作由商家端完成。其使用场景如下:

业务流程:

使用步骤:

  1. 用户登陆支付宝钱包,点击首页“付款”,进入付款码界面;
  2. 收银员在商家收银系统操作生成订单,用户确认支付金额;
  3. 用户出示钱包的“付款码”,收银员用扫码设备来扫描用户手机上的条码/二维码后,商家收银系统提交支付;
  4. 付款成功后商家收银系统会拿到支付成功或者失败的结果。

2. 扫码支付

扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。

其使用场景如下:

业务流程:

使用步骤:

  1. 用户登陆支付宝钱包,点击首页“付款-扫码付”,进入扫一扫界面;
  2. 收银员在商家收银系统操作生成支付宝订单,用户确认支付金额,并生成二维码;
  3. 用户使用钱包的“扫码付”,扫收银员提供的二维码,确认支付;
  4. 用户付款后商家收银系统会拿到支付成功或者失败的结果。

 

二、接口申请

企业在申请企业支付宝之后,进行功能申请并签约,然后在蚂蚁金服开放平台中申请应用如下(详细过程就略了)

然后在功能列表中,申请当面付这一功能,申请成功后如下。

这样,我们就有了当面付的权限了。

 

 

三、密钥生成

在支付宝当面付的接口中,使用了非对称加密算法,商户自己的公钥和私钥需要自己使用OpenSSL手动生成。对这些概念比较陌生的话,请先自行先了解一下密码学的相关知识。OpenSSL也可以从方倍工作室博客中找到。

下载支付宝官方提供的密钥生成工具OpenSSL,然后执行以下命令就可以生成公钥和私钥。

其中

genrsa -out rsa_private_key.pem 1024

是用于生成RSA私钥,执行后在程序目录中生成一个文件rsa_private_key.pem,其内容如下

复制代码

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCyffRONGd8Q/1kRh1cpsSRi360DXLHI7zxdPJGYe5HKDWF7u9b
3zZU9erZpM90XE7gZRKsxIgOurH4uqhmVRbto3e+LiYOyNpd6As3Q427KCTITasd
hHicZ6GWhegTUiVLqiuWLsauQcbI6DO4GEZrlvAdzus0WcJiJOxW02rxSQIDAQAB
AoGAXBJYyVaC4zj3Jph8YOStlR5N13bwdATdW/glWWT+0rnNEi90TQHRNvY7lNVN
JgrPrTS182TVgjOPxmwSnebakhIuGIdPq99GLE4LGd5lKWTzkd84BMvhatfNsCCz
cEVFqKg3tZd4t3fQ93FrILsnnZpLhiW53jIrStCkR3rx9OECQQDWMSHyc91hEVMQ
qVNasbGEicKWxhoDqjdm2lHkBx4mrB9JEZFDs6MxWdajf2/Qw+tgtpN3YBcCDw/H
nGHhQtStAkEA1VTyjOdAwWode8X4fu0IPq9+E19mcVOAJjLBH46mropwgOdj3123
T/ThaKeaydjabsTAiY2J18HiTiyH+1bGjQJBAKgRJXH5OFxSG7uXIbCofYJiFi34
g7EcfxxVcqxaaW4u4N2Uy0c0TXkL5T+lXzeQg8D/gfbJj0QuTVNzgdofdoECQBHY
OznCFk6Xe8PguXqUhT4JG/iu4DjWjT+kuzbSjerHtcVylY4JpZFuoHRKoM4Fj6/4
UUqwRjmABFgZrX4+sfkCQCNI8RCZ6yprh5kEOePo3uazAlNENP8dKkhgqChawdK7
7NzlJ727Nt23STHFx6NkhzyruJGQ5Vx1Lkl0wKuKbXM=
-----END RSA PRIVATE KEY-----

复制代码

命令

rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

是用于生成RSA公钥,执行后在程序目录中生成一个文件rsa_public_key.pem,其内容如下

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyffRONGd8Q/1kRh1cpsSRi360
DXLHI7zxdPJGYe5HKDWF7u9b3zZU9erZpM90XE7gZRKsxIgOurH4uqhmVRb12345
LiYOyNpd6As3Q427KCTIT7ajhHicZ6GWhegTUiVLqiuWLsauQcbI6DO4GEZrl123
zus0WcJiJOxW02rxSQIDAQAB
-----END PUBLIC KEY-----

生成的这个RSA公钥,需要填写到应用中去,填写地址如下所示。私钥不需要填到配置中,到时候配置到代码中。

 特别注意,密钥要去掉注释部分,且转换成一行字符,否则回车换行也成为密钥的一部分,将导致无法正常加解密。

 同时,可以点击 “查看支付宝公钥”,将支付宝的公钥复制保存下来,后面的程序中将需要用到。

 

四、密钥生成API与密钥配置

公共参数

请求地址:
环境HTTPS请求地址
正式环境https://openapi.alipay.com/gateway.do
公共请求参数:
参数类型是否必填最大长度描述
app_idString32支付宝分配给开发者的应用ID
methodString128接口名称
formatString40仅支持JSON
charsetString10请求使用的编码格式,如utf-8,gbk,gb2312等
sign_typeString10商户生成签名字符串所使用的签名算法类型,目前支持RSA
signString256商户请求参数的签名串,详见签名
timestampString19发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
versionString3调用的接口版本,固定为:1.0
notify_urlString256支付宝服务器主动通知商户服务器里指定的页面http/https路径。
app_auth_tokenString40详见应用授权概述
biz_contentString-请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档

请求参数

参数类型是否必填最大长度描述
out_trade_noString必须64商户订单号,64个字符以内、可包含字母、数字、下划线;需保证在商户端不重复
sceneString必须32支付场景 条码支付,取值:bar_code 声波支付,取值:wave_code
auth_codeString必须32支付授权码
seller_idString可选28如果该值为空,则默认为商户签约账号对应的支付宝用户ID
total_amountPrice可选11订单总金额,单位为元,
discountable_amountPrice可选11参与优惠计算的金额,单位为元
undiscountable_amountPrice可选11不参与优惠计算的金额,单位为元
subjectString必须256订单标题
bodyString可选128订单描述
goods_detailGoodsDetail []可选-订单包含的商品列表信息,Json格式,其它说明详见商品明细说明
operator_idString可选28商户操作员编号
store_idString可选32商户门店编号
terminal_idString可选32商户机具终端编号
alipay_store_idString可选32支付宝的店铺编号
extend_paramsExtendParams可选-业务扩展参数
timeout_expressString可选6该笔订单允许的最晚付款时间,逾期将关闭交易。
royalty_infoRoyaltyInfo可选-描述分账信息,Json格式,其它说明详见分账说明
sub_merchantSubMerchant可选-二级商户信息,当前只对特殊银行机构特定场景下使用此字段

公共响应参数

参数类型是否必填最大长度描述
codeString-网关返回码,详见文档
msgString-网关返回码描述,详见文档
sub_codeString-业务返回码,详见文档
sub_msgString-业务返回码描述,详见文档
signString-签名,详见文档

响应参数

参数类型是否必填最大长度描述
trade_noString必填64支付宝交易号
out_trade_noString必填64商户订单号
buyer_logon_idString必填100买家支付宝账号
total_amountPrice必填11交易金额
receipt_amountString必填11实收金额
buyer_pay_amountPrice选填11买家付款的金额
point_amountPrice选填11使用积分宝付款的金额
invoice_amountPrice选填11交易中可给用户开具发票的金额
gmt_paymentDate必填32交易支付时间
fund_bill_listTradeFundBill []必填-交易支付使用的资金渠道
card_balancePrice选填11支付宝卡余额
store_nameString选填512发生支付交易的商户门店名称
buyer_user_idString必填28买家在支付宝的用户id
discount_goods_detailString必填-本次交易支付所使用的单品券优惠的商品优惠信息

 

系统中配置如下

复制代码

<?php
$config = array (    
    //支付宝公钥
    'alipay_public_key' => "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOasdfiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDA123",

    //商户私钥
    'merchant_private_key' => "MIICXAIBAAKBgQCyffRONGd8Q/1kRh1cpsSRi360DXLHI7zxdPJGYe5HKDWF7u9b3zZU9erZpM90XE7gZRKsxIgOurH4uqhmVRbto3e+LiYOyNpd6As3Q427KCTIT7ajhHicZ6GWhegTUiVLqiuWLsauQcbI6DO4GEZrlvAdzus0WcJiasdfW02rxSQIDAQABAoGAXBJYyVaC4zj3Jph8YOStlR5N13bwdATdW/glWWT+0rnNEi90TQHRNvY7lNVNJgrPrTS182TVgjOPxmwSnebakhIuGIdPq99GLE4LGd5lKWTzkd84BMvhatfNsCCzcEVFqKg3tZd4t3fQ93FrILsnnZpLhiW53jIrStCkR3rx9OECQQDWMSHyc91hEVMQqVNasbGEicKWxhoDqjdm2lHkBx4mrB9JEZFDs6MxWdajf2/Qw+tgtpN3YBcCDw/HnGHhQtStAkEA1VTyjOdAwWode8X4fu0IPq9+E19mcVOAJjLBH46mropwgOdj3raqT/ThaKeaydjabsTAiY2J18HiTiyH+1bGjQJBAKgRJXH5OFxSG7uXIbCofYJiFi34g7EcfxxVcqxaaW4u4N2Uy0c0TXkL5T+lXzeQg8D/gfbJj0QuTVNzgdofdoECQBHYOznCFk6Xe8PguXqUhT4JG/iu4DjWjT+kuzbSjerHtcVylY4JpZFuoHRKoM4Fj6/4UUqwRjmABFgZrX4+sfkCQCNI8RCZ6yprh5kEOePo3uazAlNENP8dKkhgqChawdK77NzlJ727Nt23STHFx6NkhzyruJGQ5Vx1Lkl0wKuKbXM=",

    //编码格式
    'charset' => "UTF-8",

    //支付宝网关
    'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

    //应用ID
    'app_id' => "2016061501500000",

    //异步通知地址,只有扫码支付预下单可用
    'notify_url' => "http://www.fangbei.org/alipay/notify.html",

    //最大查询重试次数
    'MaxQueryRetry' => "10",

    //查询间隔
    'QueryDuration' => "3"
);

复制代码

其中支付宝公钥就是在前面中复制保存的,直接复制到程序中即可,而商户私钥是之前OpenSSL中生成的私钥。APPID是该服务的id号。

而这个异步通知将会接收扫码支付结果的通知。

 

 

五、条码支付、扫码支付、订单查询、退款申请

1. 条码支付

条码支付的参数配置如下

复制代码

// (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
// 需保证商户系统端不能重复,建议通过数据库sequence生成,
$outTradeNo = "barpay" . date('Ymdhis') . mt_rand(100, 1000);
$subject = "方倍工作室-支付宝-当面付-扫码支付";
$totalAmount = 1.21;    // (必填) 订单总金额,单位为元,不能超过1亿元

// (必填) 付款条码,用户支付宝钱包手机app点击“付款”产生的付款条码
$authCode = $_POST['auth_code']; //28开头18位数字

// 支付超时,线下扫码交易定义为5分钟
$timeExpress = "5m";

// 创建请求builder,设置请求参数
$barPayRequestBuilder = new AlipayTradePayContentBuilder();
$barPayRequestBuilder->setOutTradeNo($outTradeNo);
$barPayRequestBuilder->setTotalAmount($totalAmount);
$barPayRequestBuilder->setAuthCode($authCode);
$barPayRequestBuilder->setTimeExpress($timeExpress);
$barPayRequestBuilder->setSubject($subject);
// 调用barPay方法获取当面付应答
$barPay = new AlipayTradeService($config);
$barPayResult = $barPay->barPay($barPayRequestBuilder);

switch ($barPayResult->getTradeStatus()) {
    case "SUCCESS":
        echo "支付宝支付成功:" . "<br>--------------------------<br>";
        print_r($barPayResult->getResponse());
        break;
    case "FAILED":
        echo "支付宝支付失败!!!" . "<br>--------------------------<br>";
        if (!empty($barPayResult->getResponse())) {
            print_r($barPayResult->getResponse());
        }
        break;
    case "UNKNOWN":
        echo "系统异常,订单状态未知!!!" . "<br>--------------------------<br>";
        if (!empty($barPayResult->getResponse())) {
            print_r($barPayResult->getResponse());
        }
        break;
    default:
        echo "不支持的交易状态,交易返回异常!!!";
        break;
}
    return;
}

复制代码

程序监测,最终提交的url如下

https://openapi.alipay.com/gateway.do?app_id=2016123150150asdf&version=1.0&format=json&sign_type=RSA&method=alipay.trade.pay&timestamp=2016-08-26+17%3A14%3A52&auth_token=&alipay_sdk=alipay-sdk-php-20160411&terminal_type=&terminal_info=&prod_code=&notify_url=&charset=UTF-8&app_auth_token=&sign=EMVoBAhPkW6B1m%2BoXytdbUpIxnIAq73asdfasdfasdfYy4OcJQ2UiVTXWttw0y%2B7UEXHWILY8fYRDoNrJWSjBATrAqbGCLpPc4YBQSwtPCb%2F76d65dMQEyrEnk2sgcqhxCiJNKRoQjgAQmBQdHneerU7SwSNJ%2FfF%2F025yltZk5lzQ%3D

发送的json数据如下:

复制代码

{
    "scene":"bar_code",
    "out_trade_no":"barpay20160826051452680",
    "total_amount":0.01,
    "auth_code":"123743098312323535",
    "timeout_express":"5m",
    "subject":"方倍工作室-支付宝-当面付-扫码支付"
}

复制代码

接收到的数据如下

复制代码

{
    "alipay_trade_pay_response":{
        "code":"10000",
        "msg":"Success",
        "buyer_logon_id":"118***@qq.com",
        "buyer_pay_amount":"1.21",
        "buyer_user_id":"2088002312008751",
        "fund_bill_list":[
            {
                "amount":"0.01",
                "fund_channel":"ALIPAYACCOUNT"
            }
        ],
        "gmt_payment":"2016-08-26 17:14:59",
        "invoice_amount":"0.01",
        "open_id":"20880044751374809757987911112575",
        "out_trade_no":"barpay20160826051452680",
        "point_amount":"0.00",
        "receipt_amount":"0.01",
        "total_amount":"0.01",
        "trade_no":"2016082621001004750244100034"
    },
    "sign":"pEDeMwh6x73t9LmWrZpGnVb1npnKtasdf6+8MDUTurNPVWXR1JHT+x3cRt2G4SDNHzxkJTzSpUXjNylsWisRTnQJJzqRP5XMujxmaAHP/d5xXeyWasDag5Cj7yGD7t80buDAsdE4eoqQ6ox7KzJ6LwKcphOX13tI+Ukt1dGCQS5o="
}

复制代码

 

2. 扫码支付

扫码支付的参数配置如下

复制代码

// (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
// 需保证商户系统端不能重复,建议通过数据库sequence生成,
$outTradeNo = "qrpay".date('Ymdhis').mt_rand(100,1000);
$subject = "方倍工作室-支付宝-当面付-扫码支付";
$totalAmount = "1.01";

// 支付超时,线下扫码交易定义为5分钟
$timeExpress = "5m";

// 创建请求builder,设置请求参数
$qrPayRequestBuilder = new AlipayTradePrecreateContentBuilder();
$qrPayRequestBuilder->setOutTradeNo($outTradeNo);
$qrPayRequestBuilder->setTotalAmount($totalAmount);
$qrPayRequestBuilder->setTimeExpress($timeExpress);
$qrPayRequestBuilder->setSubject($subject);

// 调用qrPay方法获取当面付应答
$qrPay = new AlipayTradeService($config);
$qrPayResult = $qrPay->qrPay($qrPayRequestBuilder);

//    根据状态值进行业务处理
switch ($qrPayResult->getTradeStatus()){
    case "SUCCESS":
        echo "支付宝创建订单二维码成功:"."<br>---------------------------------------<br>";
        $response = $qrPayResult->getResponse();
        $qrcode = $qrPay->create_erweima($response->qr_code);
        echo $qrcode;
        print_r($response);
        
        break;
    case "FAILED":
        echo "支付宝创建订单二维码失败!!!"."<br>--------------------------<br>";
        if(!empty($qrPayResult->getResponse())){
            print_r($qrPayResult->getResponse());
        }
        break;
    case "UNKNOWN":
        echo "系统异常,状态未知!!!"."<br>--------------------------<br>";
        if(!empty($qrPayResult->getResponse())){
            print_r($qrPayResult->getResponse());
        }
        break;
    default:
        echo "不支持的返回状态,创建订单二维码返回异常!!!";
        break;
}

复制代码

生成的提交请求URL如下

https://openapi.alipay.com/gateway.do?app_id=2016061501501234&version=1.0&format=json&sign_type=RSA&method=alipay.trade.precreate&timestamp=2016-08-26+17%3A38%3A13&auth_token=&alipay_sdk=alipay-sdk-php-20160411&terminal_type=&terminal_info=&prod_code=&notify_url=http%3A%2F%2F123.daoqidata.com%2Fweixin%2Frawpost.php&charset=UTF-8&app_auth_token=&sign=ayYiJRZ63RomVEt8Ayz58Uiyv3y5IrbbXasdf16zNHkT%2Fu11U7ISUYWCXjrwrwCo2Oq2tdo%2FjtuhrBbDp5ULnTmuBBUktQDCCF53PF5yiUDGikxUPFYugeUrTg3gw4DqxOiNKM6ZB6MI0n%2F9M78a%2FnasdftZ4WthyHIl%2B%2FozSyT4%3D

发送的json数据如下:

{
    "out_trade_no":"qrpay20160826053813582",
    "total_amount":"1.01",
    "timeout_express":"5m",
    "subject":"方倍工作室-支付宝-当面付-扫码支付"
}

返回的数据如下:

复制代码

{
    "alipay_trade_precreate_response":{
        "code":"10000",
        "msg":"Success",
        "out_trade_no":"qrpay20160826053813582",
        "qr_code":"https://qr.alipay.com/bax00885xbhszseo9l7p404d"
    },
    "sign":"VfNTGo2WMZ+2CE1L05lNYWtFn4inHXO/tUaBZIBHN4fPlXnCvyc9IhS8S7wa3FYw23G30luEPEHkZWobnfpUjILonmExZVElHv3ylINz+Q2mQ5M8Sb/d61YPvf4Bgy1OvlrT4D3H/i3judmzEDBrOyFN9kB9vSkKaYC+b6L41Zw="
}

复制代码

其中的https://qr.alipay.com/bax00885xbhszseo9l7p404d 就是二维码链接地址,使用接口将其成二维码后如下所示。

当支付宝用户扫码的时候,接口通知将收到如下数据

复制代码

{
    "notify_id":"4c2c04c3cc50e978d44212febe7c3f0lse",
    "seller_email":"pay***@fangbei.org",
    "notify_type":"trade_status_sync",
    "sign":"R0iRdYmSQ0+zuSUGLzkutHasdfhoOp+CcKojVBCMa1uji3rqQFe5XeHoJB1nMBCApE3zXPKhXMdLis109ngPbGy+NUEBR7YZjYuR/hXq3WXeYfZ8aiWLvloZHrF7dQWxDho/VHYexaLeqvRi/03m0HxrwhZKUOu1eS9wMgZOlqQ=",
    "trade_no":"2016082621001004750241229810",
    "buyer_id":"2088002364008751",
    "app_id":"2016061501500000",
    "gmt_create":"2016-08-26 18:20:37",
    "out_trade_no":"qrpay20160826062009757",
    "seller_id":"2088421202724253",
    "notify_time":"2016-08-26 18:20:37",
    "subject":"方倍工作室-支付宝-当面付-扫码支付",
    "trade_status":"WAIT_BUYER_PAY",
    "open_id":"20880044751374809757987911112575",
    "total_amount":"0.01",
    "sign_type":"RSA",
    "buyer_logon_id":"118***@qq.com"
}

复制代码

当用户输入密码付款成功之后,将收到如下数据

复制代码

{
    "fund_bill_list":"[{"amount":"0.01","fundChannel":"ALIPAYACCOUNT"}]",
    "subject":"方倍工作室-支付宝-当面付-扫码支付",
    "trade_no":"2016082621001004750241229810",
    "gmt_create":"2016-08-26 18:20:37",
    "notify_type":"trade_status_sync",
    "total_amount":"0.01",
    "out_trade_no":"qrpay20160826062009757",
    "invoice_amount":"0.01",
    "open_id":"20880044751374809757987911112575",
    "seller_id":"2088421202724253",
    "notify_time":"2016-08-26 18:20:50",
    "trade_status":"TRADE_SUCCESS",
    "gmt_payment":"2016-08-26 18:20:50",
    "seller_email":"pay***@fangbei.org",
    "receipt_amount":"0.01",
    "buyer_id":"2088002364008751",
    "app_id":"2016061501500000",
    "notify_id":"56f97611ee609f46384b188b409e75else",
    "buyer_logon_id":"118***@qq.com",
    "sign_type":"RSA",
    "buyer_pay_amount":"0.01",
    "sign":"nf/KJryACk0utqlNrnuYMiSnYw6HsxqpJPk2O5MhCZ+wZUVQbrD3sq5POO3GU7LSRoSiUUIO4JEYEL12Ek2+w3lTcLS9WEi60sYowPOcJEYGmVfNZbVR6+k7yO5au2WIkM3MKsxm2XxIB9xPMmRDACGhvqZ2BXUAQujkPk1FT0s=",
    "point_amount":"0.00"
}

复制代码

 

3. 订单查询

订单查询的参数配置如下

复制代码

获取商户订单号
$out_trade_no = trim($_POST['out_trade_no']);

//第三方应用授权令牌,商户授权系统商开发模式下使用
$appAuthToken = "";//根据真实值填写

//构造查询业务请求参数对象
$queryContentBuilder = new AlipayTradeQueryContentBuilder();
$queryContentBuilder->setOutTradeNo($out_trade_no);

$queryContentBuilder->setAppAuthToken($appAuthToken);


//初始化类对象,调用queryTradeResult方法获取查询应答
$queryResponse = new AlipayTradeService($config);
$queryResult = $queryResponse->queryTradeResult($queryContentBuilder);

//根据查询返回结果状态进行业务处理
switch ($queryResult->getTradeStatus()){
    case "SUCCESS":
        echo "支付宝查询交易成功:"."<br>--------------------------<br>";
        print_r($queryResult->getResponse());
        break;
    case "FAILED":
        echo "支付宝查询交易失败或者交易已关闭!!!"."<br>--------------------------<br>";
        if(!empty($queryResult->getResponse())){
            print_r($queryResult->getResponse());
        }
        break;
    case "UNKNOWN":
        echo "系统异常,订单状态未知!!!"."<br>--------------------------<br>";
        if(!empty($queryResult->getResponse())){
            print_r($queryResult->getResponse());
        }
        break;
    default:
        echo "不支持的查询状态,交易返回异常!!!";
        break;
}

复制代码

最终提交的url如下

https://openapi.alipay.com/gateway.do?app_id=2016061501500000&version=1.0&format=json&sign_type=RSA&method=alipay.trade.query&timestamp=2016-08-26+18%3A27%3A07&auth_token=&alipay_sdk=alipay-sdk-php-20160411&terminal_type=&terminal_info=&prod_code=&notify_url=&charset=UTF-8&app_auth_token=&sign=eIuYJtes95asdf3X9eXbQzBa%2FCvm5QgQ0ToUsS8MSkCjhZACYpnU7ZT5MuD31lPZPFHVEjCKsdWiq4tuNtJPFPxirg7pkTiT09C%2Bz8PsUA844Y7hjkkX%2B4CVZcGtO11m3Ap0JECrtZW8hhJTE9bPY1v43X2BSL5Cp3Ulpac1FsM%3D

发送的json数据如下:

{
    "out_trade_no":"qrpay20160826053813582"
}

接收到的数据如下

复制代码

{
    "alipay_trade_query_response":{
        "code":"10000",
        "msg":"Success",
        "buyer_logon_id":"132***@qq.com",
        "buyer_pay_amount":"1.01",
        "buyer_user_id":"2088002364008751",
        "fund_bill_list":[
            {
                "amount":"0.01",
                "fund_channel":"ALIPAYACCOUNT"
            }
        ],
        "invoice_amount":"0.01",
        "open_id":"20880044751374809757987911112575",
        "out_trade_no":"qrpay20160826053813582",
        "point_amount":"0.00",
        "receipt_amount":"0.01",
        "send_pay_date":"2016-08-26 17:38:58",
        "total_amount":"0.01",
        "trade_no":"2016082621001004750239053830",
        "trade_status":"TRADE_SUCCESS"
    },
    "sign":"E2MxjdAhW/EqRFNkZgy/Y//dA5Cmb54Hnqa0cjBz+ZcFTULi1lvFms93onP7cpVK/fI7YxbkZTKBPk29o4aeWKXlSYCrT92domAyqahzYCA7/5A3Msc/awALYrFOdWyJJdlncWdFRN9hx52iVRIjxvLJ0hIMVIQqEDavG28HPbo="
}

复制代码

 

4. 订单退款

订单退款的参数配置如下

复制代码

$out_trade_no = trim($_POST['out_trade_no']);
$refund_amount = trim($_POST['refund_amount']);
$out_request_no = trim($_POST['out_request_no']);

//第三方应用授权令牌,商户授权系统商开发模式下使用
$appAuthToken = "";//根据真实值填写

//创建退款请求builder,设置参数
$refundRequestBuilder = new AlipayTradeRefundContentBuilder();
$refundRequestBuilder->setOutTradeNo($out_trade_no);
$refundRequestBuilder->setRefundAmount($refund_amount);
$refundRequestBuilder->setOutRequestNo($out_request_no);

$refundRequestBuilder->setAppAuthToken($appAuthToken);

//初始化类对象,调用refund获取退款应答
$refundResponse = new AlipayTradeService($config);
$refundResult =    $refundResponse->refund($refundRequestBuilder);

//根据交易状态进行处理
switch ($refundResult->getTradeStatus()){
    case "SUCCESS":
        echo "支付宝退款成功:"."<br>--------------------------<br>";
        print_r($refundResult->getResponse());
        break;
    case "FAILED":
        echo "支付宝退款失败!!!"."<br>--------------------------<br>";
        if(!empty($refundResult->getResponse())){
            print_r($refundResult->getResponse());
        }
        break;
    case "UNKNOWN":
        echo "系统异常,订单状态未知!!!"."<br>--------------------------<br>";
        if(!empty($refundResult->getResponse())){
            print_r($refundResult->getResponse());
        }
        break;
    default:
        echo "不支持的交易状态,交易返回异常!!!";
        break;
}

复制代码

最终提交的url如下

https://openapi.alipay.com/gateway.do?app_id=2016061501500000&version=1.0&format=json&sign_type=RSA&method=alipay.trade.refund&timestamp=2016-08-26+18%3A47%3A35&auth_token=&alipay_sdk=alipay-sdk-php-20160411&terminal_type=&terminal_info=&prod_code=&notify_url=&charset=UTF-8&app_auth_token=&sign=Y1c5qWglAQ0tasdfiEtqFnIJRQMn%2Fl9vMla1xgXKcExercJopMyS2rPOHaw%2F2PJEOKJC7r9qAfDGkNq4LHzXhBrD8sxLPqImPS6aWcW9p8s%2FzC2oQCJnLfaPx6lh8veHarj4WzDayeZLA48ttoQLjuMGPrITgOXYjHHyUKdBqSs%3D

发送的json数据如下:

{
    "out_trade_no":"qrpay20160826053813582",
    "refund_amount":"0.01",
    "out_request_no":"1"
}

接收到的数据如下

复制代码

{
    "alipay_trade_refund_response":{
        "code":"10000",
        "msg":"Success",
        "buyer_logon_id":"123***@qq.com",
        "buyer_user_id":"2088002364008751",
        "fund_change":"Y",
        "gmt_refund_pay":"2016-08-26 18:47:41",
        "open_id":"20880044751374809757987911112575",
        "out_trade_no":"qrpay20160826053813582",
        "refund_detail_item_list":[
            {
                "amount":"0.01",
                "fund_channel":"ALIPAYACCOUNT"
            }
        ],
        "refund_fee":"0.01",
        "send_back_fee":"0.01",
        "trade_no":"2016082621001004750239053830"
    },
    "sign":"YDNSMpX5y0rQEs0ZbfNxRFVIp8hf0W30OR74cMtwKVPO2BYee6TQC+pbnwESSZ2XSGLozTyy7o+SIa07L+FMhDv/PTt6QX1mVgQv7RhzoDkls0zDRS/5/fy9Oyj01XS1wb8Od/93iNLZDkd2yw9g0He6qGYlpcXutkmwuASd7BM="
}

复制代码

 

  

作者:txw1958 发表于 2016/08/26 18:59:20 原文链接 https://blog.csdn.net/txw1958/article/details/52330990

阅读:28497 评论:4 查看评论

 
[原]微信公众平台开发(120) 微信支付报关接口

关键字:微信支付 微信支付v3 报关接口 
作者:方倍工作室
 

本文介绍微信支付下的报关接口的开发过程。微信报关是用于商户提交海关需要的订单信息。

 

一、报关接口API

接口地址

https://api.mch.weixin.qq.com/cgi-bin/mch/customs/customdeclareorder

是否需要证书

不需要。

请求方式:post 数据格式:xml 签名方式:MD5

注意:商户订单号金额以支付系统记录的为准,无需上传,如有子订单号则必须上传子订单应付金额、物流费、商品价格(应付金额=物流费+商品价格)。 
字段名变量名必填类型示例值说明
签名signString(32)C380BEC2BFD727A4B6845133519F3AD6签名,详见签名生成算法
公众账号IDappidString(32)wxd678efh567hg6787微信分配的公众账号ID
商户号mch_idString(32)1230000109微信支付分配的商户号
商户订单号out_trade_noString(32)20150806125346商户系统内部的订单号
微信支付订单号transaction_idString(28)1000320306201511078440737890微信支付返回的订单号
海关customsString(32)SHANGHAI

NO 无需上报海关

GUANGZHOU 广州

HANGZHOU 杭州

NINGBO 宁波

ZHENGZHOU_BS 郑州(保税物流中心)

CHONGQING 重庆

XIAN 西安

SHANGHAI 上海

ZHENGZHOU_ZH 郑州(综保区)

SHENZHEN 深圳

商户海关备案号mch_customs_noString(32)123456商户在海关登记的备案号,customs非NO,此参数必填
关税dutyInt888关税,以分为单位

以下字段在拆单或重新报关时必传

字段名变量名必填类型示例值描述
商户子订单号sub_order_noString(32)20150806125346商户子订单号,如有拆单则必传
币种fee_typeString(3)CNY微信支付订单支付时使用的币种,暂只支持人民币CNY,如有拆单则必传。
应付金额order_feeInt888子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格),如有拆单则必传。
物流费transport_feeInt888物流费用,以分为单位,如有拆单则必传。
商品价格product_feeInt888商品费用,以分为单位,如有拆单则必传。

以下字段在微信缺少用户信息时必传,如果商户上传了用户信息,则以商户上传的信息为准。

字段名变量名必填类型示例值描述
证件类型cert_typeString(32)IDCARD暂只支持身份证,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备;
证件号码cert_idString(64)330821198809085211身份证号,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备;
姓名nameString(64)张三用户姓名,该参数是指用户信息,商户若有用户信息,可上送,系统将以商户上传的数据为准,进行海关通关报备;

举例如下:

复制代码

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <customs>ZHENGZHOU_BS</customs>
   <mch_customs_no>D00411</mch_customs_no>
   <mch_id>1262544101</mch_id>
   <order_fee>13110</order_fee>
   <out_trade_no>15112496832609</out_trade_no>
   <product_fee>13110</product_fee>
   <sign>8FF6CEF879FB9555CD580222E671E9D4</sign>
   <transaction_id>1006930610201511241751403478</transaction_id>
   <transport_fee>0</transport_fee>
   <fee_type>CNY</fee_type>
   <sub_order_no>15112496832609001</sub_order_no>
</xml>

复制代码

注:参数值用XML转义即可,CDATA标签用于说明数据不被XML解析器解析。

应答参数列表

字段名变量名必填类型示例值说明
返回状态码return_codeString(16)SUCCESS

SUCCESS/FAIL

此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断

返回信息return_msgString(128)签名失败

返回信息,如非空,为错误原因

签名失败

参数格式校验错误

以下字段在return_code为SUCCESS的时候有返回

字段名变量名必填类型示例值描述
签名类型sign_typeString(32)MD5暂只支持MD5
签名signString(32)C380BEC2BFD727A4B6845133519F3AD6签名,详见签名生成算法
公众账号IDappidString(32)wxd678efh567hg6787微信分配的公众账号ID
商户号mch_idString(32)1230000109微信支付分配的商户号
业务结果result_codeString(16)SUCCESSSUCCESS/FAIL
错误代码err_codeString(32)SYSTEMERROR详细参见错误列表
错误代码描述err_code_desString(128)系统错误错误返回的信息描述

以下字段在return_code 和result_code都为SUCCESS的时候有返回

字段名变量名必填类型示例值描述
状态码stateString(2)UNDECLARED

状态码

UNDECLARED -- 未申报

SUBMITTED -- 申报已提交(订单已经送海关,商户重新申报,并且海关还有修改接口,那么记录的状态会是这个)

PROCESSING -- 申报中

SUCCESS -- 申报成功

FAIL-- 申报失败

EXCEPT --海关接口异常

微信支付订单号transaction_idString(28)1000320306201511078440737890微信支付返回的订单号
商户订单号out_trade_noString(32)20150806125346商户系统内部的订单号
商户子订单号sub_order_noString(32)20150806125346商户子订单号,如有拆单则必传
微信子订单号sub_order_idString(32)20150806125346微信子订单号
最后更新时间modify_timeString(14)20091227091010最后更新时间,格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自微信服务器

错误码

名称描述原因解决方案
132011004参数错误报关时仅传入订单号,不传入子订单号(sub_order_no)时,不能填费用信息,须以支付系统中的值为准请检查参数是否都正确
132021028交易币种与商户结算币种不一致】报关时传入子订单号(sub_order_no)时,币种参数(fee_type)必填请检查所传币种参数(fee_type)是否为空
MCHID_NOT_SET商户号未设置商户号为必传参数,请求时必传请检查商户号是否为空
MCHID_INVALID_LENGTH无效的商户号长度报关接口只支持12开头10位数字的商户号请检查商户号长度是否为10位
CUSTOMSCONFIG_NOT_SET海关配置未设置报关接口需要商户已配置过海关信息才可以访问请参照上文中的海关备案指引,进行海关信息报备
FEETYPE_NOT_SET币种类型未设置拆单情况下,币种为必填参数请检查fee_type是否为空
OUTTRADENO_NOT_SET商户订单号(out_trade_no)未设置商户订单号为必传参数请检查商户订单号(out_trade_no)是否为空
TRANSACTION_ID_NOT_SET微信订单号(transaction_id)未设置微信订单号(transaction_id)为必传参数请检查微信订单号(transaction_id)是否为空
INVALID_TRANSACTION_ID无效的微信订单号长度微信订单号为28位数字,请确保长度一致请检查微信订单号(transaction_id)是否正确
CUSTOMS_NOT_SET海关信息未设置海关信息为必传字段请检查海关信息是否为空
CHCUSTOMSNO_NOT_SET海关备案号未设置海关备案号为必传字段请检查备案号是否为空
INVALID_MCHCUSTOMSNO无效的海关备案号长度海关备案号一般为6位字符串请检查海关备案号是否正确
PAYFEE_NOT_MATCH金额不匹配报关的订单金额必须和支付的金额一致请检查报关订单的金额是否正确
INVALID_SUBORDER_NO无效的子订单号长度(sub_order_no)子订单号要求是32位以内的字符串请检查子订单号长度是否正确
APPID_NOT_EXISTAppId未设置(sub_order_no)appid为必传字段请检查appid是否正确
MCHID_NOT_EXIST商户号(mch_id)未设置MCH_ID为必传字段请检查mch_id是否正确
AUTHORITY_NOT_FOUND未开通自助清关功能须先开通自助清关功能才可成功调用接口请检查是否已开通自助清关功能,开通路径:微信支付商户平台-产品中心-自助清关中申请开通。
NO_AUTH无权限未获得此接口的调用权限请检查当前商户号是否已获得此接口的调用权限

 

二、SDK实现

sdk定义

 

 

三、调用方式

 

四、返回结果

发送数据如下

array(6) {
  ["appid"]=>
  string(18) "wxa8092dd025e45123"
  ["mch_id"]=>
  string(10) "1238298123"
  ["out_trade_no"]=>
  string(22) "SH20160824095750086988"
  ["transaction_id"]=>
  string(28) "4006742001201608242098415582"
  ["customs"]=>
  string(6) "NINGBO"
  ["mch_customs_no"]=>
  string(10) "3302461123"
}

接收到的数据如下

array(12) {
  ["return_code"]=>
  string(7) "SUCCESS"
  ["return_msg"]=>
  string(6) "成功"
  ["sign"]=>
  string(32) "91EFCEEAAD4322F331F3F63C4D8F1279"
  ["appid"]=>
  string(18) "wxa8092dd025e45123"
  ["mch_id"]=>
  string(10) "1238298123"
  ["result_code"]=>
  string(7) "SUCCESS"
  ["err_code"]=>
  string(1) "0"
  ["err_code_des"]=>
  string(2) "OK"
  ["state"]=>
  string(9) "SUBMITTED"
  ["transaction_id"]=>
  string(28) "4006742001201608242098415582"
  ["out_trade_no"]=>
  string(22) "SH20160824095750086988"
  ["modify_time"]=>
  string(14) "20160825111049"
}

 

作者:txw1958 发表于 2016/08/25 11:49:22 原文链接 https://blog.csdn.net/txw1958/article/details/52313224

阅读:4028 评论:3 查看评论

 
[原]微信支付开发(7) 刷卡支付

关键字:微信支付 微信支付v3 刷卡支付 统一支付 prepay_id 
作者:方倍工作室
 

本文介绍微信支付下的刷卡支付的开发过程。微信刷卡支付是指用户打开微信钱包的刷卡的界面,商户扫码后提交完成支付的支付过程。

 

 

一、刷卡支付API

接口地址

https://api.mch.weixin.qq.com/pay/micropay

是否需要证书

不需要。

输入参数

名称变量名必填类型示例值描述
公众账号IDappidString(32)wx8888888888888888微信分配的公众账号ID(企业号corpid即为此appId)
商户号mch_idString(32)1900000109微信支付分配的商户号
设备号device_infoString(32)013467007045764终端设备号(商户自定义,如门店编号)
随机字符串nonce_strString(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS随机字符串,不长于32位。推荐随机数生成算法
签名signString(32)C380BEC2BFD727A4B6845133519F3AD6签名,详见签名生成算法
商品描述bodyString(128)image形象店-深圳腾大- QQ公仔商品简单描述,该字段须严格按照规范传递,具体请见参数规定
商品详情detailString(6000){
"goods_detail":[
{
"goods_id":"iphone6s_16G",
"wxpay_goods_id":"1001",
"goods_name":"iPhone6s 16G",
"goods_num":1,
"price":528800,
"goods_category":"123456",
"body":"苹果手机"
},
{
"goods_id":"iphone6s_32G",
"wxpay_goods_id":"1002",
"goods_name":"iPhone6s 32G",
"quantity":1,
"price":608800,
"goods_category":"123789",
"body":"苹果手机"
}
]
}

商品详细列表,使用Json格式,传输签名前请务必使用CDATA标签将JSON文本串保护起来。

goods_detail []:
└ goods_id String 必填 32 商品的编号
└ wxpay_goods_id String 可选 32 微信支付定义的统一商品编号
└ goods_name String 必填 256 商品名称
└ goods_num Int 必填 商品数量
└ price Int 必填 商品单价,单位为分
└ goods_category String 可选 32 商品类目ID
└ body String 可选 1000 商品描述信息

附加数据attachString(127)说明附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
商户订单号out_trade_noString(32)1217752501201407033233368018商户系统内部的订单号,32个字符内、可包含字母,其他说明见商户订单号
商品详情detailString(8192)与提交数据一致

实际提交的返回

订单金额total_feeInt888订单总金额,单位为分,只能为整数,详见支付金额
货币类型fee_typeString(16)CNY符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
终端IPspbill_create_ipString(16)8.8.8.8调用微信支付API的机器IP
商品标记goods_tagString(32) 商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
指定支付方式limit_payString(32)no_creditno_credit--指定不能使用信用卡支付
授权码auth_codeString(128)120061098828009406扫码支付授权码,设备读取用户微信中的条码或者二维码信息

举例如下:

复制代码

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <attach>订单额外描述</attach>
   <auth_code>120269300684844649</auth_code>
   <body>刷卡支付测试</body>
   <device_info>1000</device_info>
   <goods_tag></goods_tag>
   <mch_id>10000100</mch_id>
   <nonce_str>8aaee146b1dee7cec9100add9b96cbe2</nonce_str>
   <out_trade_no>1415757673</out_trade_no>
   <spbill_create_ip>14.17.22.52</spbill_create_ip>
   <time_expire></time_expire>
   <total_fee>1</total_fee>
   <sign>C29DB7DB1FD4136B84AE35604756362C</sign>
</xml>

复制代码

注:参数值用XML转义即可,CDATA标签用于说明数据不被XML解析器解析。

返回结果

名称变量名必填类型示例值描述
返回状态码return_codeString(16)SUCCESSSUCCESS/FAIL 
此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
返回信息return_msgString(128)签名失败返回信息,如非空,为错误原因 
签名失败 
参数格式校验错误

当return_code为SUCCESS的时候,还会包括以下字段:

名称变量名必填类型示例值描述
公众账号IDappidString(32)wx8888888888888888调用接口提交的公众账号ID
商户号mch_idString(32)1900000109调用接口提交的商户号
设备号device_infoString(32)013467007045764调用接口提交的终端设备号,
随机字符串nonce_strString(32)5K8264ILTKCH16CQ2502SI8ZNMTM67VS微信返回的随机字符串
签名signString(32)C380BEC2BFD727A4B6845133519F3AD6微信返回的签名,详见签名生成算法
业务结果result_codeString(16)SUCCESSSUCCESS/FAIL
错误代码err_codeString(32)SYSTEMERROR详细参见错误列表
错误代码描述err_code_desString(128)系统错误错误返回的信息描述

当return_code 和result_code都为SUCCESS的时,还会包括以下字段:

名称变量名必填类型示例值描述
用户标识openidString(128)Y用户在商户appid 下的唯一标识
是否关注公众账号is_subscribeString(1)Y用户是否关注公众账号,仅在公众账号类型支付有效,取值范围:Y或N;Y-关注;N-未关注
交易类型trade_typeString(16)MICROPAY支付类型为MICROPAY(即扫码支付)
付款银行bank_typeString(16)CMC银行类型,采用字符串类型的银行标识,值列表详见银行类型
货币类型fee_typeString(16)CNY符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
订单金额total_feeInt888订单总金额,单位为分,只能为整数,详见支付金额
现金支付货币类型cash_fee_typeString(16)CNY符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
现金支付金额cash_feeInt100订单现金支付金额,详见支付金额
微信支付订单号transaction_idString(32)1217752501201407033233368018微信支付订单号
商户订单号out_trade_noString(32)1217752501201407033233368018商户系统的订单号,与请求一致。
商家数据包attachString(128)123456商家数据包,原样返回
支付完成时间time_endString(14)20141030133525订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。详见时间规则

举例如下:

<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <device_info><![CDATA[1000]]></device_info>
   <nonce_str><![CDATA[GOp3TRyMXzbMlkun]]></nonce_str>
   <sign><![CDATA[D6C76CB785F07992CDE05494BB7DF7FD]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>
   <is_subscribe><![CDATA[Y]]></is_subscribe>
   <trade_type><![CDATA[MICROPAY]]></trade_type>
   <bank_type><![CDATA[CCB_DEBIT]]></bank_type>
   <total_fee>1</total_fee>
   <coupon_fee>0</coupon_fee>
   <fee_type><![CDATA[CNY]]></fee_type>
   <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>
   <out_trade_no><![CDATA[1415757673]]></out_trade_no>
   <attach><![CDATA[订单额外描述]]></attach>
   <time_end><![CDATA[20141111170043]]></time_end>
</xml>

 

二、刷卡支付类实现

在微信支付原来的微信支付类文件中,仿照统一支付类的方式,添加刷卡支付类如下:

/**
 * 刷卡支付接口类
 */
class MicroPay_pub extends Wxpay_client_pub
{    
    function __construct() 
    {
        //设置接口链接
        $this->url = "https://api.mch.weixin.qq.com/pay/micropay";
        //设置curl超时时间
        $this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;
    }
    
    /**
     * 生成接口参数xml
     */
    function createXml()
    {
        try
        {
            //检测必填参数
            if($this->parameters["out_trade_no"] == null){
                throw new SDKRuntimeException("缺少统一支付接口必填参数out_trade_no!"."<br>");
            }elseif($this->parameters["body"] == null){
                throw new SDKRuntimeException("缺少统一支付接口必填参数body!"."<br>");
            }elseif ($this->parameters["total_fee"] == null ) {
                throw new SDKRuntimeException("缺少统一支付接口必填参数total_fee!"."<br>");
            }elseif ($this->parameters["auth_code"] == null) {
                throw new SDKRuntimeException("缺少统一支付接口必填参数auth_code!"."<br>");
            }
               $this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
               $this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
               $this->parameters["spbill_create_ip"] = $_SERVER['REMOTE_ADDR'];//终端ip        
            $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
            $this->parameters["sign"] = $this->getSign($this->parameters);//签名
            // var_dump($this->parameters);
            return  $this->arrayToXml($this->parameters);
        }catch (SDKRuntimeException $e)
        {
            die($e->errorMessage());
        }
    }
}

原有的基础类和请求类也列出如下:

/**
 * 所有接口的基类
 */
class Common_util_pub
{
    function __construct() {
    }

    function trimString($value)
    {
        $ret = null;
        if (null != $value) 
        {
            $ret = $value;
            if (strlen($ret) == 0) 
            {
                $ret = null;
            }
        }
        return $ret;
    }
    
    /**
     *     作用:产生随机字符串,不长于32位
     */
    public function createNoncestr( $length = 32 ) 
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {  
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
        }  
        return $str;
    }
    
    /**
     *     作用:格式化参数,签名过程需要使用
     */
    function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v)
        {
            if($urlencode)
            {
               $v = urlencode($v);
            }
            //$buff .= strtolower($k) . "=" . $v . "&";
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar;
        if (strlen($buff) > 0) 
        {
            $reqPar = substr($buff, 0, strlen($buff)-1);
        }
        return $reqPar;
    }
    
    /**
     *     作用:生成签名
     */
    public function getSign($Obj)
    {
        foreach ($Obj as $k => $v)
        {
            $Parameters[$k] = $v;
        }
        //签名步骤一:按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //echo '【string1】'.$String.'</br>';
        //签名步骤二:在string后加入KEY
        $String = $String."&key=".WxPayConf_pub::KEY;
        //echo "【string2】".$String."</br>";
        //签名步骤三:MD5加密
        $String = md5($String);
        //echo "【string3】 ".$String."</br>";
        //签名步骤四:所有字符转为大写
        $result_ = strtoupper($String);
        //echo "【result】 ".$result_."</br>";
        return $result_;
    }
    
    /**
     *     作用:array转xml
     */
    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; 
    }
    
    /**
     *     作用:将xml转为array
     */
    public function xmlToArray($xml)
    {        
        //将XML转为array        
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        
        return $array_data;
    }

    /**
     *     作用:以post方式提交xml到对应的接口url
     */
    public function postXmlCurl($xml,$url,$second=30)
    {        
        //初始化curl        
           $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOP_TIMEOUT, $second);
        //这里设置代理,如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        curl_close($ch);
        //返回结果
        if($data)
        {
            curl_close($ch);
            return $data;
        }
        else 
        { 
            $error = curl_errno($ch);
            echo "curl出错,错误码:$error"."<br>"; 
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }

    /**
     *     作用:使用证书,以post方式提交xml到对应的接口url
     */
    function postXmlSSLCurl($xml,$url,$second=30)
    {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        //这里设置代理,如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch,CURLOPT_HEADER,FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
        //设置证书
        //使用证书:cert 与 key 分别属于两个.pem文件
        //默认格式为PEM,可以注释
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT, dirname(__FILE__).WxPayConf_pub::SSLCERT_PATH);
        //默认格式为PEM,可以注释
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY, dirname(__FILE__).WxPayConf_pub::SSLKEY_PATH);
        //post提交方式
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        }
        else { 
            $error = curl_errno($ch);
            echo "curl出错,错误码:$error"."<br>"; 
            echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
            curl_close($ch);
            return false;
        }
    }
    
    /**
     *     作用:打印数组
     */
    function printErr($wording='',$err='')
    {
        print_r('<pre>');
        echo $wording."</br>";
        var_dump($err);
        print_r('</pre>');
    }
}

/**
 * 请求型接口的基类
 */
class Wxpay_client_pub extends Common_util_pub 
{
    var $parameters;//请求参数,类型为关联数组
    public $response;//微信返回的响应
    public $result;//返回参数,类型为关联数组
    var $url;//接口链接
    var $curl_timeout;//curl超时时间
    
    /**
     *     作用:设置请求参数
     */
    function setParameter($parameter, $parameterValue)
    {
        $this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
    }
    
    /**
     *     作用:设置标配的请求参数,生成签名,生成接口参数xml
     */
    function createXml()
    {
           $this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
           $this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
        $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
        $this->parameters["sign"] = $this->getSign($this->parameters);//签名
        return  $this->arrayToXml($this->parameters);
    }
    
    /**
     *     作用:post请求xml
     */
    function postXml()
    {
        $xml = $this->createXml();
        $this->response = $this->postXmlCurl($xml,$this->url,$this->curl_timeout);
        return $this->response;
    }
    
    /**
     *     作用:使用证书post请求xml
     */
    function postXmlSSL()
    {    
        $xml = $this->createXml();
        $this->response = $this->postXmlSSLCurl($xml,$this->url,$this->curl_timeout);
        return $this->response;
    }

    /**
     *     作用:获取结果,默认不使用证书
     */
    function getResult() 
    {        
        $this->postXml();
        $this->result = $this->xmlToArray($this->response);
        return $this->result;
    }
}

 

 

三、发起支付

在程序中,获得用户的授权码,并填入到$authcode参数中。授权码就是条码上的那一串18位纯数字,以10、11、12、13、14、15开头

其他参数则自动生成或者手动输入指定。

调用函数如下所示

        //全局引入微信支付类
        Vendor('Wxpay.WxPayPubHelper.WxPayPubHelper');
        //使用统一支付接口
        $microPay = new \MicroPay_pub();
        //设置统一支付接口参数
        $microPay->setParameter("body","方倍商户刷卡支付");//商品描述
        $microPay->setParameter("out_trade_no", "$out_trade_no");//商户订单号 
        $microPay->setParameter("total_fee", $total_fee);//总金额  
        $microPay->setParameter("auth_code", $authcode);//授权码

        //获取统一支付接口结果
        $microPayResult = $microPay->getResult();

        //3. 异常判断
        if (!isset($microPayResult["result_code"]) || ($microPayResult["result_code"] == "FAIL")) {
            $this->resRpcError(isset($microPayResult['result_code']) ? $microPayResult['err_code_des'] : $microPayResult['return_msg'], "21000");
        }

 

作者:txw1958 发表于 2016/08/24 19:48:55 原文链接 https://blog.csdn.net/txw1958/article/details/52303451

阅读:8395 评论:2 查看评论

 
[原]PHP中XML和数组互相转换的方法

转换代码如下

    //数组转XML
    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;
    }

    //将XML转为array
    function xmlToArray($xml)
    {    
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);        
        return $values;
    }

 

Array转XML

$money = 101;
$sender = "方倍工作室";
$obj2 = array();
$obj2['wxappid']             = APPID;
$obj2['mch_id']             = MCHID;
$obj2['mch_billno']            = MCHID.date('YmdHis').rand(1000, 9999);
$obj2['client_ip']            = $_SERVER['REMOTE_ADDR'];
$obj2['re_openid']             = $openid;
$obj2['total_amount']       = $money;
$obj2['min_value']             = $money;
$obj2['max_value']             = $money;
$obj2['total_num']             = 1;
$obj2['nick_name']          = $sender;
$obj2['send_name']          = $sender;
$obj2['wishing']            = "恭喜发财";
$obj2['act_name']              = "方倍工作室送红包";
$obj2['remark']              = "关注公众账号";

转换后

<xml>
  <wxappid><![CDATA[wx1b7559b818e3c123]]></wxappid>
  <mch_id>1235571234</mch_id>
  <mch_billno>1235571234201605241726128109</mch_billno>
  <client_ip><![CDATA[127.0.0.1]]></client_ip>
  <re_openid><![CDATA[oiPuduGV7gJ_MOSfAWpVmhhgXh-U]]></re_openid>
  <total_amount>101</total_amount>
  <min_value>101</min_value>
  <max_value>101</max_value>
  <total_num>1</total_num>
  <nick_name><![CDATA[方倍工作室]]></nick_name>
  <send_name><![CDATA[方倍工作室]]></send_name>
  <wishing><![CDATA[恭喜发财]]></wishing>
  <act_name><![CDATA[方倍工作室送红包]]></act_name>
  <remark><![CDATA[关注公众账号]]></remark>
</xml>

 

 

 

XML转为Array

 

<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[发放成功]]></return_msg>
<result_code><![CDATA[SUCCESS]]></result_code>
<err_code><![CDATA[MONEY_LIMIT]]></err_code>
<err_code_des><![CDATA[发放成功]></err_code_des>
<mch_billno><![CDATA[1235571234201605241651123985]]></mch_billno>
<mch_id>1235571234</mch_id>
<wxappid><![CDATA[wx1b7559b818e3c123]]></wxappid>
<re_openid><![CDATA[oiPuduGV7gJ_MOSfAWpVmhhgXh-U]]></re_openid>
<total_amount>1</total_amount>
</xml>

 

转换后

 

array(10) {
  ["return_code"]=>
  string(7) "SUCCESS"
  ["return_msg"]=>
  string(12) "发放成功"
  ["result_code"]=>
  string(7) "SUCCESS"
  ["err_code"]=>
  string(11) "MONEY_LIMIT"
  ["err_code_des"]=>
  string(12) "发放成功"
  ["mch_billno"]=>
  string(28) "1235571234201605241651123985"
  ["mch_id"]=>
  string(10) "1235571234"
  ["wxappid"]=>
  string(18) "wx1b7559b818e3c123"
  ["re_openid"]=>
  string(28) "oiPuduGV7gJ_MOSfAWpVmhhgXh-U"
  ["total_amount"]=>
  string(1) "1"
}

 

 

作者:txw1958 发表于 2016/05/24 17:34:22 原文链接 https://blog.csdn.net/txw1958/article/details/51492118

阅读:9881

 
[原]微信支付开发(7) 收货地址共享接口V2

在这篇微信公众平台开发教程中,我们将介绍如何在网页中实现获取收货地址的功能。

收货地址共享接口 在2016年4月13日 进行过升级,2016年5月20日之后只能使用新接口,本教程为新版接口的教程!

本文分为以下二个部分:

  1. 生成JS-SDK权限验证签名
  2. 实现获取共享收货地址

 

一、微信JS-SDK

1. 获得Access Token

access token的获得方法在前面有介绍,详情见 微信公众平台开发(26) ACCESS TOKEN

2. 获取jsapi_ticket

生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket),接口地址如下

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

成功返回如下JSON:

{
    "errcode":0,
    "errmsg":"ok",
    "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
    "expires_in":7200
}

获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。

3. 签名算法实现

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

即signature=sha1(string1)。 示例:

noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com?params=value

步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

步骤2. 对string1进行sha1签名,得到signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

完整代码如下

<?php
class JSSDK {
  private $appId;
  private $appSecret;

  public function __construct($appId, $appSecret) {
    $this->appId = $appId;
    $this->appSecret = $appSecret;
  }

  public function getSignPackage() {
    $jsapiTicket = $this->getJsApiTicket();

    // 注意 URL 一定要动态获取,不能 hardcode.
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

    $timestamp = time();
    $nonceStr = $this->createNonceStr();

    // 这里参数的顺序要按照 key 值 ASCII 码升序排序
    $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

    $signature = sha1($string);

    $signPackage = array(
      "appId"     => $this->appId,
      "nonceStr"  => $nonceStr,
      "timestamp" => $timestamp,
      "url"       => $url,
      "signature" => $signature,
      "rawString" => $string
    );
    return $signPackage; 
  }

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

  private function getJsApiTicket() {
    // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
    $data = json_decode(file_get_contents("jsapi_ticket.json"));
    if ($data->expire_time < time()) {
      $accessToken = $this->getAccessToken();
      // 如果是企业号用以下 URL 获取 ticket
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
      $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
      $res = json_decode($this->httpGet($url));
      $ticket = $res->ticket;
      if ($ticket) {
        $data->expire_time = time() + 7000;
        $data->jsapi_ticket = $ticket;
        $fp = fopen("jsapi_ticket.json", "w");
        fwrite($fp, json_encode($data));
        fclose($fp);
      }
    } else {
      $ticket = $data->jsapi_ticket;
    }

    return $ticket;
  }

  private function getAccessToken() {
    // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
    $data = json_decode(file_get_contents("access_token.json"));
    if ($data->expire_time < time()) {
      // 如果是企业号用以下URL获取access_token
      // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
      $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
      $res = json_decode($this->httpGet($url));
      $access_token = $res->access_token;
      if ($access_token) {
        $data->expire_time = time() + 7000;
        $data->access_token = $access_token;
        $fp = fopen("access_token.json", "w");
        fwrite($fp, json_encode($data));
        fclose($fp);
      }
    } else {
      $access_token = $data->access_token;
    }
    return $access_token;
  }

  private function httpGet($url) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);

    $res = curl_exec($curl);
    curl_close($curl);

    return $res;
  }
}

 

二、收货地址共享接口

1. 简介

微信收货地址共享,是指用户在微信浏览器内打开网页,填写过地址后,后续可以免填写支持快速选择,也可增加和编辑。此地址为用户属性,可在各商户的网页中共享使用。支持原生控件填写地址,地址数据会传递到商户。

地址共享是基于微信JavaScript API 实现,只能在微信内置浏览器中使用,其他浏览器调用无效。同时,需要微信5.0 版本才能支持,建议通过user agent 来确定用户当前的版本号后再调用地址接口。以iPhone 版本为例,可以通过useragent可获取如下微信版本示例信息:"Mozilla/5.0(iphone;CPU iphone OS 5_1_1 like Mac OS X)AppleWebKit/534.46(KHTML,like Geocko) Mobile/9B206MicroMessenger/5.0"其中5.0 为用户安装的微信版本号,商户可以判定版本号是否高于或者等于5.0。

地址格式
微信地址共享使用的数据字段包括:

  • 收货人姓名
  • 地区,省市区三级
  • 详细地址
  • 邮编
  • 联系电话

其中,地区对应是国标三级地区码,如“广东省-广州市-天河区”,对应的邮编是是510630。详情参考链接:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201401/t20140116_501070.html

2. 绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。

3. 获取签名包

<?php
require_once "jssdk.php";
$jssdk = new JSSDK("yourAppID", "yourAppSecret");
$signPackage = $jssdk->GetSignPackage();
?>

4. 引入JS文件

在需要调用JS接口的页面引入如下JS文件:

特别注意:JS-SDK版本需使用http://res.wx.qq.com/open/js/jweixin-1.1.0.js

<script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>

5.通过config接口注入权限验证配置

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。

        <script>
          wx.config({
            debug: false,
            appId: '<?php echo $signPackage["appId"];?>',
            timestamp: <?php echo $signPackage["timestamp"];?>,
            nonceStr: '<?php echo $signPackage["nonceStr"];?>',
            signature: '<?php echo $signPackage["signature"];?>',
            jsApiList: [
              // 所有要调用的 API 都要加到这个列表中
                'checkJsApi',
                'openAddress',
              ]
          });
        </script>

6. 通过ready接口处理成功验证

需要在页面加载时就调用,需要把相关接口放在ready函数中调用来确保正确执行

wx.ready(function () {
});

7. 通过checkJsApi判断当前客户端版本是否支持分享参数自定义

 wx.checkJsApi({
                jsApiList: [
                    'openAddress',
                ],
                success: function (res) {
                    alert(JSON.stringify(res));
                }
            });  

8. 实现收货地址共享

            wx.openAddress({
              trigger: function (res) {
                alert('用户开始拉出地址');
              },
              success: function (res) {
                alert('用户成功拉出地址');
                alert(JSON.stringify(res));
                document.form1.address1.value         = res.provinceName;
                document.form1.address2.value         = res.cityName;
                document.form1.address3.value         = res.countryName;
                document.form1.detail.value           = res.detailInfo;
                document.form1.national.value         = res.nationalCode;
                document.form1.user.value            = res.userName;
                document.form1.phone.value            = res.telNumber;
                document.form1.postcode.value         = res.postalCode;
                document.form1.errmsg.value         = res.errMsg;
                document.form1.qq.value             = 1354386063;
              },
              cancel: function (res) {
                alert('用户取消拉出地址');
              },
              fail: function (res) {
                alert(JSON.stringify(res));
              }
            });

返回说明

返回值

说明

errMsg

获取编辑收货地址成功返回“openAddress:ok”。

userName

收货人姓名。

postalCode

邮编。

provinceName

国标收货地址第一级地址(省)。

cityName

国标收货地址第二级地址(市)。

countryName

国标收货地址第三级地址(国家)。

detailInfo

详细收货地址信息。

nationalCode

收货地址国家码。

 

三、实现效果

    

作者:txw1958 发表于 2016/04/19 18:58:19 原文链接 https://blog.csdn.net/txw1958/article/details/51193081

阅读:6467 评论:2 查看评论

 
[原]微信开放平台开发(3) 移动应用微信登录

在这篇微信公众平台开发教程中,我们将介绍如何使用微信开放平台接口实现移动应用微信登录的功能。

 

移动应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。

在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的移动应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。

1、目前移动应用上微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用。

2、对于Android应用,建议总是显示微信登录按钮,当用户手机没有安装微信客户端时,请引导用户下载安装微信客户端。

3、对于iOS应用,考虑到iOS应用商店审核指南中的相关规定,建议开发者接入微信登录时,先检测用户手机是否已安装微信客户端(使用sdk中isWXAppInstalled函数 ),对未安装的用户隐藏微信登录按钮,只提供其他登录方式(比如手机号注册登录、游客登录等)。

授权流程说明

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:

1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;

3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

获取access_token时序图:

 

第一步:请求CODE

移动应用微信授权登录

开发者需要配合使用微信开放平台提供的SDK进行授权登录请求接入。正确接入SDK后并拥有相关授权域(scope,什么是授权域?)权限后,开发者移动应用会在终端本地拉起微信应用进行授权登录,微信用户确认后微信将拉起开发者移动应用,并带上授权临时票据(code)。

iOS平台应用授权登录接入代码示例(请参考iOS接入指南):

-(void)sendAuthRequest
{ 
    //构造SendAuthReq结构体 
    SendAuthReq* req =[[[SendAuthReq alloc ] init ] autorelease ];
    req.scope = @"snsapi_userinfo" ;
    req.state = @"123" ;
    //第三方向微信终端发送一个SendAuthReq消息结构
    [WXApi sendReq:req]; 
}

Android平台应用授权登录接入代码示例(请参考Android接入指南):

{ 
    // send oauth request 
    Final SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";
    req.state = "wechat_sdk_demo_test";
    api.sendReq(req);
}

参数说明

参数是否必须说明
appid应用唯一标识,在微信开放平台提交应用审核通过后获得
scope应用授权作用域,如获取用户个人信息则填写snsapi_userinfo(什么是授权域?
state用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

 

返回示例:

appid: wxd477edab60670232
scope: snsapi_userinfo
state: wechat_sdk_demo

可拉起微信打开授权登录页:

返回说明

用户点击授权后,微信客户端会被拉起,跳转至授权界面,用户在该界面点击允许或取消,SDK通过SendAuth的Resp返回数据给调用方。

 

返回值说明
ErrCodeERR_OK = 0(用户同意)
ERR_AUTH_DENIED = -4(用户拒绝授权)
ERR_USER_CANCEL = -2(用户取消)
code用户换取access_token的code,仅在ErrCode为0时有效
state第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K
lang微信客户端当前语言
country微信用户当前国家信息

第二步:通过code获取access_token

获取第一步的code后,请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数是否必须说明
appid应用唯一标识,在微信开放平台提交应用审核通过后获得
secret应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
code填写第一步获取的code参数
grant_type填authorization_code

 

返回如下

{
    "access_token": "OezXcEiiBSKSxW0eoylIeOZ0dfxvb93UyrFdwznvwUv3JkVNVV1yFvQQa3IfuyMi4iZGDsAfe81sCaUXxyKrI-5XgCvhAS02eAC4MF2fJFl80Y9s-0h1EsuBmIVKgu0GnKhxCQ0M8G-gkQAJpzLzmQ",
    "expires_in": 7200,
    "refresh_token": "OezXcEiiBSKSxW0eoylIeOZ0dfxvb93UyrFdwznvwUv3JkVNVV1yFvQQa3IfuyMiH7dCabGFyMRtZHnHPHuEK78cf1eISYJ4y453T8pDa2tFAIJu8bFeLMBpeFSv9dgnGrK-ZfRxHzhq7IW4qevEMQ",
    "openid": "oH9d2v7NmDhsFzICG63UPSIOgUcY",
    "scope": "snsapi_userinfo",
    "unionid": "o4wcnwx0BVC4F_hSl5qCd5rC4Jps"
}

参数说明

参数说明
access_token接口调用凭证
expires_inaccess_token接口调用凭证超时时间,单位(秒)
refresh_token用户刷新access_token
openid授权用户唯一标识
scope用户授权的作用域,使用逗号(,)分隔
unionid 当且仅当该移动应用已获得该用户的userinfo授权时,才会出现该字段

 

获取用户个人信息(UnionID机制)

接口说明

此接口用于获取用户个人信息。开发者可通过OpenID来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。请注意,在用户修改微信头像后,旧的微信头像URL将会失效,因此开发者应该自己在获取用户信息后,将头像图片保存下来,避免微信头像URL失效后的异常情况。

请求说明

http请求方式: GET

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数是否必须说明
access_token调用凭证
openid普通用户的标识,对当前开发者帐号唯一
  lang  否国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN
{
    "openid": "oH9d2v7NmDhsFzICG63UPSIOgUcY",
    "nickname": "方倍",
    "sex": 0,
    "language": "zh_CN",
    "city": "",
    "province": "",
    "country": "CN",
    "headimgurl": "http://wx.qlogo.cn/mmopen/pburdzLK7PUTcFw3ozK52Gravkznno51DSjnqnzsG6WzJLUOtadGBYYSVqh5YDicdawxrD6hHoR96OcyyDWAEgA/0",
    "privilege": [],
    "unionid": "o4wcnwx0BVC4F_hSl5qCd5rC4Jps"
}

参数说明

参数说明
openid普通用户的标识,对当前开发者帐号唯一
nickname普通用户昵称
sex普通用户性别,1为男性,2为女性
province普通用户个人资料填写的省份
city普通用户个人资料填写的城市
country国家,如中国为CN
headimgurl用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
unionid用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。

 

 

完整PHP SDK

class class_app
{
    var $appid = APPID;
    var $appsecret = APPSECRET;

    //构造函数
    public function __construct($appid = NULL, $appsecret = NULL)
    {
        if($appid && $appsecret){
            $this->appid = $appid;
            $this->appsecret = $appsecret;
        }
    }

    //通过code获取access_token
    public function oauth2_access_token($code)
    {
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->appsecret."&code=".$code."&grant_type=authorization_code";
        $res = $this->http_request($url);
        return json_decode($res, true);
    }

    //获取用户个人信息(UnionID机制)
    public function oauth2_get_user_info($access_token, $openid)
    {
        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $res = $this->http_request($url);
        return json_decode($res, true);
    }

    //HTTP请求(支持HTTP/HTTPS,支持GET/POST)
    protected function http_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    //日志记录
    private function logger($log_content)
    {
        if(isset($_SERVER['HTTP_APPNAME'])){   //SAE
            sae_set_display_errors(false);
            sae_debug($log_content);
            sae_set_display_errors(true);
        }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
            $max_size = 500000;
            $log_filename = "log.xml";
            if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
            file_put_contents($log_filename, date('Y-m-d H:i:s').$log_content."\r\n", FILE_APPEND);
        }
    }
}

调用方法

/*
    方倍工作室 http://www.fangbei.org/
    CopyRight 2014 All Rights Reserved
    微信开放平台 移动应用 (微信登录)
*/
header("Content-type: text/html; charset=utf-8");


define('APPID',            "wx3f05f4b79761d123");
define('APPSECRET',        "9acc222b92afb29cff90b9bcfc7d6080");

$code = "041359a1b393c92a5a509ce24e2ef50f";


$weixin = new class_app();
var_dump($weixin);

//传入授权临时票据(code)
$oauth2_info = $weixin->oauth2_access_token($code);
var_dump($oauth2_info);

$result = $weixin->oauth2_get_user_info($oauth2_info['access_token'], $oauth2_info['openid']);
var_dump($result);

 

 

 

作者:txw1958 发表于 2016/04/15 18:38:09 原文链接 https://blog.csdn.net/txw1958/article/details/51163903

阅读:11812

 
[原]微信支付v3开发(5) 扫码并输入金额支付

关键字:微信支付 微信支付v3 动态native支付 统一支付 Native支付 prepay_id 
作者:方倍工作室

 

本文介绍微信支付下的扫描二维码并输入自定义金额的支付的开发过程。

注意

微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版。V3版的微信支付没有paySignKey参数。v2的相关介绍请参考方倍工作室的其他文章。本文介绍的为微信支付v3。

 

一. OAuth2.0授权

JSAPI 支付前需要调用 登录授权接口获取到用户的 Openid 。所以需要做一次授权,这次授权是不弹出确认框的。
其实质就是在用户访问

http://www.fangbei.org/wxpay/js_api_call.php

时跳转到

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8888888888888888&redirect_uri=http://www.fangbei.org/wxpay/js_api_call.php&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect

以此来获得code参数,并根据code来获得授权access_token及openid

其实现的详细流程可参考 微信公众平台开发(71)OAuth2.0网页授权

 

二、获取用户输入金额

上述流程中是获得用户的openid,另外还需要获得本次的交易金额。

复制代码

    <body onselectstart="return true;" οndragstart="return false;">
        <form method="post" action="submit.php" id="form" οnsubmit="return tgSubmit()">
            <div class="container gray_bg">
                <div class="explain">
                    <h3>
                         企业微信支付-扫码自定义金额
                    </h3>
                </div>
                <div class="box apply_box" id="applyBox">
                    <dl class="pb15">
                        <dt>
                            金额(¥)
                        </dt>
                        <dd>
                            <input name="amount" class="txt required" id="amount" value="" placeholder="请输入数字金额,单位元" type="tel" οnkeyup="checkNum(this)"/>
                        </dd>
                        
                    </dl>
                </div>
                <footer class="sub_wrap">
                    <input type="hidden" name="openid" value="<?php echo $openid;?>">
                    <input type="submit" class="btn mt20" id="subBtn" value="提交" />
                    <div class="copyright">技术支持 方倍工作室
                    </div>
                </footer>
            </div>
        </form>
    </body>

复制代码

 

三、拉取支付插件

获得openid和金额之后,直接使用统一订单接口输入参数

复制代码

    $jsApi = new JsApi_pub();
    
    //=========步骤2:使用统一支付接口,获取prepay_id============
    //使用统一支付接口
    $unifiedOrder = new UnifiedOrder_pub();
    
    //设置统一支付接口参数
    //设置必填参数
    //appid已填,商户无需重复填写
    //mch_id已填,商户无需重复填写
    //noncestr已填,商户无需重复填写
    //spbill_create_ip已填,商户无需重复填写
    //sign已填,商户无需重复填写
    $unifiedOrder->setParameter("openid","$openid");//商品描述
    $unifiedOrder->setParameter("body","自定义价格扫码商品");//商品描述
    //自定义订单号,此处仅作举例
    $timeStamp = time();
    $out_trade_no = WxPayConf_pub::APPID."$timeStamp";
    $unifiedOrder->setParameter("out_trade_no","$out_trade_no");//商户订单号 
    $unifiedOrder->setParameter("total_fee",($amount * 100));//总金额
    $unifiedOrder->setParameter("notify_url",WxPayConf_pub::NOTIFY_URL);//通知地址 
    $unifiedOrder->setParameter("trade_type","JSAPI");//交易类型
    //非必填参数,商户可根据实际情况选填
    //$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号  
    // $unifiedOrder->setParameter("device_info","XXXX");//设备号 
    //$unifiedOrder->setParameter("attach","XXXX");//附加数据 
    //$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间
    //$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 
    //$unifiedOrder->setParameter("goods_tag","XXXX");//商品标记 
    //$unifiedOrder->setParameter("openid","XXXX");//用户标识
    $unifiedOrder->setParameter("product_id","XXXX");//商品ID

    $prepay_id = $unifiedOrder->getPrepayId();
    // logger("prepay_id ".$prepay_id);
    //=========步骤3:使用jsapi调起支付============
    $jsApi->setPrepayId($prepay_id);

    $jsApiParameters = $jsApi->getParameters();

复制代码

详细流程,可以参考 微信支付开发(1) JS API支付

 

四、效果展示

扫描二维码

 

  

作者:txw1958 发表于 2016/03/30 18:58:28 原文链接 https://blog.csdn.net/txw1958/article/details/51018270

阅读:33921 评论:3 查看评论

 
[原]微信支付v3开发(6) 收货地址共享接口

 

请看新版教程  微信支付开发(7) 收货地址共享接口V2

 

 

本文介绍微信支付下的收货地址共享接口的开发过程。

一. 简介

微信收货地址共享,是指用户在微信浏览器内打开网页,填写过地址后,后续可以免填写支持快速选择,也可增加和编辑。此地址为用户属性,可在各商户的网页中共享使用。支持原生控件填写地址,地址数据会传递到商户。

地址共享是基于微信JavaScript API 实现,只能在微信内置浏览器中使用,其他浏览器调用无效。同时,需要微信5.0 版本才能支持,建议通过user agent 来确定用户当前的版本号后再调用地址接口。以iPhone 版本为例,可以通过useragent可获取如下微信版本示例信息:"Mozilla/5.0(iphone;CPU iphone OS 5_1_1 like Mac OS X)AppleWebKit/534.46(KHTML,like Geocko) Mobile/9B206MicroMessenger/5.0"其中5.0 为用户安装的微信版本号,商户可以判定版本号是否高于或者等于5.0。

地址格式
微信地址共享使用的数据字段包括:

  • 收货人姓名
  • 地区,省市区三级
  • 详细地址
  • 邮编
  • 联系电话

其中,地区对应是国标三级地区码,如“广东省-广州市-天河区”,对应的邮编是是510630。详情参考链接:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201401/t20140116_501070.html

 

二. OAuth2.0授权

获取收货地址之前前需要调用 登录授权接口获取到一次OAuth2.0的Access Token 。所以需要做一次授权,这次授权是不弹出确认框的。
其实质就是在用户访问

http://www.fangbei.org/wxpay/js_api_call.php

时跳转到

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8888888888888888&redirect_uri=http://www.fangbei.org/wxpay/js_api_call.php&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect

以此来获得code参数,并根据code来获得授权access_token及openid,这个access token将用于收货地址共享接口。

其实现的详细流程可参考 微信公众平台开发(71)OAuth2.0网页授权

 

二、获取随机字符串

生成随机字符串的方法如下

 

三、生成签名

参与addrSign 签名的字段包括:appId、url(调用JavaScript API的网页url)、timestamp、noncestr、accessToken
对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。
这里需要注意的是签名过程中所有参数名均为小写字符,例如appId 在排序后字符串则为appid;
对string1作签名算法,字段名和字段值都采用原始值,不进行URL 转义。具体签名算法为addrSign = SHA1(string1)。这里给出生成addrSign 的具体示例如下:

appId=wx17ef1eaef46752cb
url=http://open.weixin.qq.com/
timeStamp=1384841012
nonceStr=123456
accessToken=OezXcEiiBSKSxW0eoylIeBFk1b8VbNtfWALJ5g6aMgZHaqZwK4euEskSn78Qd5pLsfQtuMdgmhajVM5QDm24W8X3tJ18kz5mhmkUcI3RoLm7qGgh1cEnCHejWQo8s5L3VvsFAdawhFxUuLmgh5FRA

i:经过a过程键值对排序后得到string1 为:

accesstoken=OezXcEiiBSKSxW0eoylIeBFk1b8VbNtfWALJ5g6aMgZHaqZwK4euEskSn78Qd5pLsfQtuMdgmhajVM5QDm24W8X3tJ18kz5mhmkUcI3RoLm7qGgh1cEnCHejWQo8s5L3VvsFAdawhFxUuLmgh5FRA&appid=wx17ef1eaef46752cb&noncestr=123456&timestamp=1384841012&url=http://open.weixin.qq.com/?code=CODE&state=STATE

ii:经过b过程签名后可得到:

addrSign=SHA1(accesstoken=OezXcEiiBSKSxW0eoylIeBFk1b8VbNtfWALJ5g6aMgZHaqZwK4euEskSn78Qd5pLsfQtuMdgmhajVM5QDm24W8X3tJ18kz5mhmkUcI3RoLm7qGgh1cEnCHejWQo8s5L3VvsFAdawhFxUuLmg
h5FRA&appid=wx17ef1eaef46752cb&noncestr=123456&timestamp=1384841012&url=http://open.weixin.qq.com/?code=CODE&state=STATE)=ca604c740945587544a9cc25e58dd090f200e6fb

实现代码如下

 

四、获得收货地址

编辑并获取用户收货地址editAddress接口,在网页前端调用。
参数列表:

参数必填说明
appId公众号appID
scope填写“jsapi_address”,获得编辑地址权限
signType签名方式,目前仅支持SHA1
addrSign签名,由各参数一起参与签名生成
timeStamp时间戳
nonceStr随机字符串

调用方法如下

参数返回:

返回值说明
err_msgedit_address:ok获取编辑收货地址成功
edit_address:fail获取编辑收货地址失败
username收货人姓名
telNumber收货人电话
addressPostalCode邮编
proviceFirstStageName国标收货地址第一级地址
addressCitySecondStageName国标收货地址第二级地址
addressCountiesThirdStageName国标收货地址第三级地址
addressDetailInfo详细收货地址信息
nationalCode收货地址国家码

 

 

五、示例

    

 

作者:txw1958 发表于 2016/03/30 18:55:13 原文链接 https://blog.csdn.net/txw1958/article/details/51018227

阅读:2574

 
[原]PHP调用内容DES加密的SOAP接口

本文以方倍工作室优惠券接口开发为例,介绍PHP下DES加解密及SOAP接口调用的实现过程。


一、基础概念

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1976年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),随后在国际上广泛流传开来。

DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。 明文按64位进行分组,密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1)分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。

 

SOAP(Simple Object Access Protocol )简单对象访问协议是在分散或分布式的环境中交换信息的简单的协议,是一个基于XML的协议,它包括四个部分:SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们的框架;SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例; SOAP RPC表示(RPC representation),表示远程过程调用和应答的协定;SOAP绑定(binding),使用底层协议交换信息。

WSDL(Web Service Description Language)就是描述XML Web服务的标准XML格式,WSDL由Ariba、Intel、IBM和微软等开发商提出。它用一种和具体语言无关的抽象方式定义了给定Web服务收发的有关操作和消息。就其定义来说,你还不能把WSDL当作一种对象接口定义语言,例如,CORBA或COM等应用程序体系结构就会用到对象接口定义语言。 WSDL保持协议中立,但它确实内建了绑定SOAP的支持,从而同SOAP建立了不可分割的联系。所以,当我在这篇文章中讨论WSDL的时候,我会假定你把SOAP作为了你的通讯协议。

SOAP和WSDL虽然是web service的两大标准,但是两者并没有必然的联系,都可以独立使用。它们之间的关系就类似HTTP和Html之间的关系。前者是一种协议,后者是对一个Web Server的描述。


二、PHP下的配置

在php的的配置文件php.ini中,找到

extension=php_soap.dll

然后将前面的;号去掉,然后重启web服务

探针查看环境,需要支持mcrypt和soap

 

 

三、DES加解密

Des的类如下,其中iv向量使用固定值。

复制代码

 1 /* 
 2      方倍工作室
 3      http://www.fangbei.org
 4 */
 5 
 6 class DES
 7 {
 8     var $key;
 9     var $iv;
10 
11     function DES($key)
12     {
13         $this->key = $key;
14         $bytes = array(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
15         $this->iv =  $this->bytesToStr($bytes);
16         // $this->iv =  mcrypt_create_iv ( mcrypt_get_block_size (MCRYPT_DES, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM );
17     }
18 
19     //加密,返回大写十六进制字符串
20     function encrypt($str) 
21     {
22         $size = mcrypt_get_block_size ( MCRYPT_DES, MCRYPT_MODE_CBC );
23         $str = $this->pkcs5Pad ( $str, $size );
24         return strtoupper( bin2hex( mcrypt_cbc(MCRYPT_DES, $this->key, $str, MCRYPT_ENCRYPT, $this->iv ) ) );
25     }
26 
27     //解密
28     function decrypt($str) 
29     {
30         $strBin = $this->hex2bin( strtolower( $str ) );
31         $str = mcrypt_cbc( MCRYPT_DES, $this->key, $strBin, MCRYPT_DECRYPT, $this->iv );
32         $str = $this->pkcs5Unpad( $str );
33         return $str;
34     }
35 
36     function hex2bin($hexData) 
37     {
38         $binData = "";
39         for($i = 0; $i < strlen ( $hexData ); $i += 2) {
40             $binData .= chr ( hexdec ( substr ( $hexData, $i, 2 ) ) );
41         }
42         return $binData;
43     }
44 
45     function pkcs5Pad($text, $blocksize) 
46     {
47         $pad = $blocksize - (strlen ( $text ) % $blocksize);
48         return $text . str_repeat ( chr ( $pad ), $pad );
49     }
50 
51     function pkcs5Unpad($text) 
52     {
53         $pad = ord ( $text {strlen ( $text ) - 1} );
54         if ($pad > strlen ( $text ))
55             return false;
56         if (strspn ( $text, chr ( $pad ), strlen ( $text ) - $pad ) != $pad)
57             return false;
58         return substr ( $text, 0, - 1 * $pad );
59     }
60 
61     function bytesToStr($bytes)
62     {
63         $str = '';
64         foreach($bytes as $ch) {
65             $str .= chr($ch);
66         }
67         return $str;
68     }
69 }

复制代码

 

四、准备入参

首先需要获得当前订单号,订单号为20160322185825271格式。

实现代码如下

1 list($millisecond, $second)=explode(' ',microtime());
2 $timestamp = date("YmdHis",$second);
3 $orderno = $timestamp.substr($millisecond, 2, 3);

然后调用DES进行加密

1 $crypt = new DES($desKey);
2 $XMLParam = $crypt->encrypt($XMLData);

明文为 

<GetVoucher><machinecode>000000000</machinecode><vtype>VTRMB</vtype><data>10</data><validdays>30</validdays><totalmoney>10</totalmoney><ordercode>20160322185825271</ordercode></GetVoucher>

加密后为

13FDFAF455E7A5516829F73FA6017EC55F54385CD3F15EC0C09FA429F30450504494B024CFA659DCD44A752A84421CDC8010C0B9C1C1B7F027AF1B24F138C08132DF05A923529478B1824BC7533B3A7A2F37F4CA76A8D52E820F6E491A801F9A0B13A69B6ABB4B092143751A7258A4D3935CDD8175091E7F6FE4F3F3964438117621F22B5133681C517C9D4DABE551C323D0D6DB5D563631AD0910D5C51E4DD46133C4FEE3AEC95DFD212F1A70546F7468C1A21168B024CDEA27A097157D08D7

 

五、PHP调用SOAP协议接口

调用方法如下

复制代码

1 try {
2     $client = new SoapClient('http://www.fangbei.org/VoucherService.asmx?WSDL');
3     $result = $client->GetVoucher(array('XmlParam'=>$XMLParam, 'UserName'=>$UserName,'Sign'=>$Sign));
4     var_dump($result);
5     $encryptVoucherResult = $result->GetVoucherResult;
6 } catch (SOAPFault $e) {
7     print_r('Exception:'.$e);
8 }

复制代码

result结果如下

复制代码

object(stdClass)#2 (1) {
  ["GetVoucherResult"]=>
  string(464) "6F036F920E11B1069FC97B5A7CBF5BBB77B58B63980251864C75ECB3D7D34E453B88D50B32B3330F9415B5B54FF03DB082EB5CA9C8C5CCE0664A030BC1BB1541E297B0983E06FDEFCF772F14DA4A0B70F395562BA31BDAED0CA0978680825BA810E8B40FAB24E73562CC782DB897193553FF3724BF86E9863134B9CEA25635D2BCF435B33936896C4E0C257E8CC77D6E017DA4782FE6058CEBABD832EE33E47878B305D89647F8D119C33C24181CCC1A610C286E312B77FF9E02D4077A0C303902DC185D3915BE4BC493661F8212AB98C325C46E242357E7D15A5033956A43F8C651374590D4727F"
}

复制代码

有用的内容为加密的

6F036F920E11B1069FC97B5A7CBF5BBB77B58B63980251864C75ECB3D7D34E453B88D50B32B3330F9415B5B54FF03DB082EB5CA9C8C5CCE0664A030BC1BB1541E297B0983E06FDEFCF772F14DA4A0B70F395562BA31BDAED0CA0978680825BA810E8B40FAB24E73562CC782DB897193553FF3724BF86E9863134B9CEA25635D2BCF435B33936896C4E0C257E8CC77D6E017DA4782FE6058CEBABD832EE33E47878B305D89647F8D119C33C24181CCC1A610C286E312B77FF9E02D4077A0C303902DC185D3915BE4BC493661F8212AB98C325C46E242357E7D15A5033956A43F8C651374590D4727F

对其进行DES解密

1 $decryptVoucherResult = $crypt->decrypt($encryptVoucherResult);
2 var_dump($decryptVoucherResult);

返回内容为XML

<Result><status>1</status><uuid>A5C0CFAE06644038AA53A50DF6CD159C</uuid><extractcode></extractcode><datamatrix>zwH3FAtTwhP7h2zWSe65q7qWdoWqzph5nZ/XUBJP89N/rYIn14k+WxDL+ukchZvKXHdCxs6r6YCBoTIcgW0hgIHg4ULu9C6p</datamatrix></Result>

再将XML转成PHP数组,代码如下

1 $obj = json_decode(json_encode(simplexml_load_string($decryptVoucherResult)),TRUE);
2 var_dump($obj);

返回数组如下

复制代码

array(4) {
  ["status"]=>
  string(1) "1"
  ["uuid"]=>
  string(32) "A5C0CFAE06644038AA53A50DF6CD159C"
  ["extractcode"]=>
  array(0) {}
  ["datamatrix"]=>
  string(96) "zwH3FAtTwhP7h2zWSe65q7qWdoWqzph5nZ/XUBJP89N/rYIn14k+WxDL+ukchZvKXHdCxs6r6YCBoTIcgW0hgIHg4ULu9C6p"
}

复制代码

 

作者:txw1958 发表于 2016/03/30 18:48:35 原文链接 https://blog.csdn.net/txw1958/article/details/51018179

阅读:1375

 
[原]使用MySQL统计页面访问及排名

统计访问页面数量,以分辨率进行排名

 

	SELECT CONCAT(`height` , '*', `width`) AS `resolution` , COUNT(CONCAT(`height`, '*', `width`)) AS `total` 
	FROM `wifi_status_page` 
	GROUP BY CONCAT(`height`, '*', `width`) 
	ORDER BY `total` DESC 
	LIMIT 0 , 30

最近7天页面访问量,每日统计数量,以日期为序

 

 

	SELECT td AS showdate, COALESCE( totalcount, 0 ) AS totalcount 
	FROM (
		SELECT CURDATE( ) AS td
		UNION ALL SELECT DATE_ADD( CURDATE( ) , INTERVAL -1 DAY ) 
		UNION ALL SELECT DATE_ADD( CURDATE( ) , INTERVAL -2 DAY ) 
		UNION ALL SELECT DATE_ADD( CURDATE( ) , INTERVAL -3 DAY ) 
		UNION ALL SELECT DATE_ADD( CURDATE( ) , INTERVAL -4 DAY ) 
		UNION ALL SELECT DATE_ADD( CURDATE( ) , INTERVAL -5 DAY ) 
		UNION ALL SELECT DATE_ADD( CURDATE( ) , INTERVAL -6 DAY ) 
		ORDER BY td
	)a
	LEFT JOIN (
		SELECT FROM_UNIXTIME(add_time, '%Y-%m-%d') add_data, COUNT( id ) AS totalcount
		FROM wifi_status_page
		WHERE FROM_UNIXTIME(add_time, '%Y-%m-%d') BETWEEN DATE_ADD(CURDATE(), INTERVAL -6 DAY) AND CURDATE() 
		GROUP BY add_data
	)b ON a.td = b.add_data

最近30天页面访问量,每日统计数量,以日期为序

 

 

SELECT td AS showdate, COALESCE( totalcount, 0 ) AS totalcount 
	FROM (
		SELECT CURDATE( ) AS td
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -1 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -2 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -3 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -4 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -5 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -6 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -7 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -8 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -9 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -10 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -11 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -12 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -13 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -14 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -15 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -16 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -17 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -18 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -19 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -20 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -21 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -22 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -23 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -24 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -25 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -26 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -27 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -28 DAY)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -29 DAY)
		ORDER BY td
	)a
	LEFT JOIN (
		SELECT FROM_UNIXTIME(add_time, '%Y-%m-%d') add_data, COUNT( id ) AS totalcount
		FROM wifi_status_page
		WHERE FROM_UNIXTIME(add_time, '%Y-%m-%d') BETWEEN DATE_ADD(CURDATE(), INTERVAL -29 DAY) AND CURDATE() 
		GROUP BY add_data
	)b ON a.td = b.add_data
 

昨天24小时分时

 

	SELECT td AS showhour
	FROM (
		SELECT DATE_ADD(CURDATE(), INTERVAL -1 HOUR) as td
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -2 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -3 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -4 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -5 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -6 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -7 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -8 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -9 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -10 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -11 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -12 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -13 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -14 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -15 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -16 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -17 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -18 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -19 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -20 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -21 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -22 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -23 HOUR)
		UNION ALL SELECT DATE_ADD(CURDATE(), INTERVAL -24 HOUR)
		ORDER BY td
	)a
 

今天过去的11个小时

 

	SELECT td AS showhour
	FROM (
		SELECT NOW() AS td
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -1 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -2 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -3 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -4 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -5 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -6 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -7 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -8 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -9 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -10 HOUR)
		UNION ALL SELECT DATE_ADD(NOW(), INTERVAL -11 HOUR)
		ORDER BY td
	)a
 

 

 

 

 

作者:txw1958 发表于 2016/01/22 17:42:28 原文链接 https://blog.csdn.net/txw1958/article/details/50563449

阅读:2323 评论:1 查看评论

 
[原]微信公众平台开发(111) 现金红包、裂变红包、企业付款
关键字:微信公众平台 微信红包 现金红包 裂变红包 企业付款 
作者:方倍工作室 
原文:http://www.cnblogs.com/txw1958/p/wxpay-mkt-transfer.html 

 

在这篇微信公众平台开发教程中,我们将介绍如何在实现现金红包、裂变红包、企业付款以及红包交易查询(含现金红包和裂变红包)和企业付款查询的功能。

本文分为以下二个部分:

  1. 微信支付接口SDK定义
  2. 现金红包、裂变红包、企业付款的调用方法

 

一、微信红包SDK

现金红包、裂变红包、企业付款本质均为商户和用户之间的转账,微信官方定义其接口时,操作方法类似。

1. 请求URL

现金红包

https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack

裂变红包

https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack

企业付款

https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers

2. 参数说明

字段名变量名必填示例值类型描述
随机字符串nonce_str5K8264ILTKCH16CQ2502SI8ZNMTM67VSString(32)随机字符串,不长于32位
签名signC380BEC2BFD727A4B6845133519F3AD6String(32)详见签名生成算法
商户订单号mch_billno10000098201411100000000000String(28)商户订单号(每个订单号必须唯一)
商户号mch_id10000098String(32)微信支付分配的商户号
公众账号appidwxappidwx8888888888888888String(32)微信分配的公众账号ID(企业号corpid即为此appId)。
商户名称send_name天虹百货String(32)红包发送者名称
用户openidre_openidoxTWIuGaIt6gTKsQRLau2M0yL16EString(32)接受红包的用户用户在wxappid下的openid
付款金额total_amount1000int付款金额,单位分
红包发放总人数total_num1int红包发放总人数
红包祝福语wishing感谢您参加猜灯谜活动,祝您元宵节快乐!String(128)红包祝福语
Ip地址client_ip192.168.0.1String(15)调用接口的机器Ip地址
活动名称act_name猜灯谜抢红包活动String(32)活动名称
备注remark猜越多得越多,快来抢!String(256)备注信息
红包金额设置方式amt_typeALL_RANDString(32)红包金额设置方式ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
校验用户姓名选项check_nameOPTION_CHECKStringNO_CHECK:不校验真实姓名 
FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) 
OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
收款用户姓名re_user_name可选方倍String收款用户真实姓名。 如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名
金额amount10099int企业付款金额,单位为分
企业付款描述信息desc理赔String企业付款操作说明信息。必填。
Ip地址spbill_create_ip192.168.0.1String(32)调用接口的机器Ip地址

3. 请求示例

<xml>
    <mch_appid>wxe062425f740c30d8</mch_appid>
    <mchid>10000098</mchid>
    <nonce_str>3PG2J4ILTKCH16CQ2502SI8ZNMTM67VS</nonce_str>
    <partner_trade_no>100000982014120919616</partner_trade_no>
    <openid>ohO4Gt7wVPxIT1A9GjFaMYMiZY1s</openid>
    <check_name>OPTION_CHECK</check_name>
    <re_user_name>张三</re_user_name>
    <amount>100</amount>
    <desc>节日快乐!</desc>
    <spbill_create_ip>10.2.3.10</spbill_create_ip>
    <sign>C97BDBACF37622775366F38B629F45E3</sign>
</xml>

4. 返回示例

成功示例:

<xml>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <return_msg><![CDATA[]]></return_msg>
    <mch_appid><![CDATA[wxec38b8ff840bd989]]></mch_appid>
    <mchid><![CDATA[10013274]]></mchid>
    <device_info><![CDATA[]]></device_info>
    <nonce_str><![CDATA[lxuDzMnRjpcXzxLx0q]]></nonce_str>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <partner_trade_no><![CDATA[10013574201505191526582441]]></partner_trade_no>
    <payment_no><![CDATA[1000018301201505190181489473]]></payment_no>
    <payment_time><![CDATA[2015-05-19 15:26:59]]></payment_time>
</xml>

错误示例:

<xml>
    <return_code><![CDATA[FAIL]]></return_code>
    <return_msg><![CDATA[系统繁忙,请稍后再试.]]></return_msg>
    <result_code><![CDATA[FAIL]]></result_code>
    <err_code><![CDATA[SYSTEMERROR]]></err_code>
    <err_code_des><![CDATA[系统繁忙,请稍后再试.]]></err_code_des>
</xml>

 

二、SDK实现

sdk定义

 

三、调用方式

1. 企业付款调用方法

2. 现金红包调用方法

3. 裂变红包调用方法

4. 红包查询调用方法

5. 企业付款查询调用方法

 

四、实现效果

   

 

 

作者:txw1958 发表于 2016/01/16 11:33:07 原文链接 https://blog.csdn.net/txw1958/article/details/50527405

阅读:2977 评论:1 查看评论

 
[原]微信公众平台开发入门教程
关键字:微信公众平台开发
作者:方倍工作室

 

在这篇微信公众平台开发教程中,我们假定你已经有了PHP语言程序、MySQL数据库、计算机网络通讯、及HTTP/XML/CSS/JS等基础。

我们将使用微信公众账号方倍工作室作为讲解的例子,二维码见底部。

本系列教程将引导你完成如下任务:

  1. 创建新浪云计算平台应用
  2. 启用微信公众平台开发模式
  3. 了解数据收发原理及消息格式
  4. 开发实现微信天气预报功能

 

第一章 申请服务器资源

创建新浪云计算应用

申请账号

我们使用SAE新浪云计算平台作为服务器资源,并且申请PHP环境+MySQL数据库作为程序运行环境。
申请地址为:

http://www.sinacloud.com/

直接点击上述网址,可以看到右上角微博登录的链接。

点击进入之后,使用新浪微博账号登录 

实名认证

新浪SAE要求用户上传身份证进行实名认证才可以正常使用,在左侧菜单列表中可以找到“实名认证”这一标签可进行实名认证操作。实名认证过程是免费的。认证以后每月免费有5G的流量。认证审核需要1~3个工作日。

来不及准备身份证照片的话可以先继续下面的内容,改天再来进行实名认证。但在使用过程中会受点影响。

如果不进行实名认证,SAE会在回复的内容中会带上干扰的html内容信息,从而导致Token验证失败或者该公众号暂时无法提供服务,请稍后再试。

实名认证需要填的信息如下


实名认证成功后,将如下图所示。

充值(本步骤可选择性进行)

新浪云SAE实行的是配额免费+超额付费的方式,相关标准请查看SAE价格体系介绍。初期对于大部分用户来说免费配额已够用,如果您将来使用量比较大建议预先至少充值100元获得10000云豆,以免超额后应用被禁用而影响业务。

创建新应用 http://www.cnblogs.com/txw1958/p/wechat-tutorial.html 

回到首页,在菜单顶部选择 控制台 ,再选择 云应用SAE 

进入SAE应用列表

点击下侧的创建新应用,这时会弹出提示, 禁止放置违法违规内容,点击继续创建,弹出如下窗口。

选择一个未使用的appid,如果老是已经被使用不知道该什么好,就填写你的QQ号或者手机号吧。

填写二级域名AppID、应用名称、验证码,开发语言选择PHP5.3,全部应用和框架下面选择第一个【PHP 空应用】。然后点击左下方的创建应用

 

应用创建成功。并自动跳转到应用列表中,可以看到已经有刚才创建的1354386063这个应用。

创建数据库 

点击刚才创建的应用名称,进入应用主页。

在左侧的数据库服务中找到MySQL

点击进入MySQL类型选择,这里选择独享型MySQL

在创建独享型MySQL中,使用微型配置,然后点击“确认初始化”

底部将显示任务进度。

等任务完成之后,再点击销毁MySQL按钮,

这样创建并销毁一次,可以多获得200云豆。以后使用的时候,可以使用免费的共享型MySQL或者使用收费但更稳定强大的独享型MySQL。

创建版本 http://www.cnblogs.com/txw1958/p/wechat-tutorial.html 

点击刚才创建的应用名称,进入应用主页。

点击左侧的应用管理下面的代码管理

 

在代码管理中,选择使用SVN托管的方式,不要使用git的方式。

跳转到代码管理

点击右侧的“创建版本”

版本号默认为1,点击创建,有时会弹出安全登录,需要输入安全密码,如果不知道或者忘记了,就点里面的找回密码,重新设置一下。:

验证通过之后,如下所示

到这里,就成功创建了一个域名URL为 http://1354386063.sinaapp.com/ 的应用了,记住你的这个URL,后面将会用到。

 原文:http://www.cnblogs.com/txw1958/p/wechat-tutorial.html 

上传代码 http://www.cnblogs.com/txw1958/p/wechat-tutorial.html 

下述代码是一个微信接口文件,看不懂没有关系,你可以暂时不用弄明白它的意思。

如果想弄明白,可以购买《微信公众平台开发最佳实践》,在该书中第25页~第27页有详细讲解。

<?php
/*
    方倍工作室 http://www.cnblogs.com/txw1958/
    CopyRight 2013 www.doucube.com  All Rights Reserved
*/

define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (isset($_GET['echostr'])) {
    $wechatObj->valid();
}else{
    $wechatObj->responseMsg();
}

class wechatCallbackapiTest
{
    public function valid()
    {
        $echoStr = $_GET["echostr"];
        if($this->checkSignature()){
            header('content-type:text');
            echo $echoStr;
            exit;
        }
    }

    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );

        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }

    public function responseMsg()
    {
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

        if (!empty($postStr)){
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $fromUsername = $postObj->FromUserName;
            $toUsername = $postObj->ToUserName;
            $keyword = trim($postObj->Content);
            $time = time();
            $textTpl = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[%s]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                        <FuncFlag>0</FuncFlag>
                        </xml>";
            if($keyword == "?" || $keyword == "?")
            {
                $msgType = "text";
                $contentStr = date("Y-m-d H:i:s",time());
                $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                echo $resultStr;
            }
        }else{
            echo "";
            exit;
        }
    }
}
?>

我们将使用上述代码与微信公众平台对接。

将上述代码用专业的软件存为utf-8格式的index.php文件后再使用WinRAR压缩为index.zip,

或者直接下载方倍工作室已经压缩好的index.zip文件。点此进入下载

回到SAE的代码管理界面中。

再选择“上传代码包”,点击上传文件,选择刚才的index.zip文件,点击上传,上传成功后中间是一个绿色的横条,如下所示

如果没有绿色的横条,表示上传失败,需要重试。可以考虑在Chrome浏览器下重试一下。

点击编辑代码按钮,

 有时候需要输入自己的安全密码,如果不记得了就点击“找回密码”。

安全验证成功后继续之前的操作。

我们可以看到index.php已经上传成功,双击可以查看编辑里面的代码

新浪云应用的创建就成功了。

 

第二章 启用开发模式

微信公众平台开发模式

高级功能

微信公众平台地址:https://mp.weixin.qq.com 

登录微信公众平台后台,在左侧列表中最下方,找到“ 基本配置 ”,点击进入

进入服务器配置填写框。

点击“修改配置”按钮

此处的URL为上篇中介绍的云应用的域名,而Token在index.php中定义为weixin。EncodingAESKey则不用填,点击“随机生成”让自动生成一个,消息加解密方式选择“明文模式”,然后点击“提交”按钮。

 

在弹出的提示框中,点击“确定”

配置修改后如图所示,再点击“启用”按钮

询问“是否确定开启服务器配置”,点击“确定”

如果提示“token验证失败”,可以先重次几次,微信服务器有时候不稳定。并确保你的SAE已经上传身份证通过实名认证!

如果还是失败,请先用微信调试器测试一下url和token是否正确,点此查看详细测试方法

成功启用后如图。

恭喜,你成功启用开发模式。

 

自动回复

在上面的例子中,实现了一个发送“?”就能回复当前时间的功能。
效果如下:

至此,你的微信公众平台账号已经实现自动回复了。 

 

第三章 数据收发原理及消息数据格式

 

★ 本章是理论部分,初学者会比较难以理解,不用太过追究。

开发模式成为开发者时的消息校验原理

在开发者首次提交验证申请时,微信服务器将发送GET请求到填写的URL上,并且带上四个参数(signature、timestamp、nonce、echostr),开发者通过对签名(即signature)的效验,来判断此条消息的真实性。

此后,每次开发者接收用户消息的时候,微信也都会带上前面三个参数(signature、timestamp、nonce)访问开发者设置的URL,开发者依然通过对签名的效验判断此条消息的真实性。效验方式与首次提交验证申请一致。

参数描述
signature微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp时间戳
nonce随机数
echostr随机字符串

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。

加密/校验流程如下:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

启用接口是由代码中的checkSignature()函数来实现校验的。如果对这一原理难以理解,可以暂时不用深究,继续看下面。

 

成为开发者后消息收发时的原理

上一章节中图,当用户发送一个“?”时,系统回复了一个时间

这一原理的消息流程图如下所示。

从上图可以看出,用户在发送一个?后,微信服务器将组装一个消息发送给我们自己的服务器,自己的服务器然后回复一个时间,并且将该时间也按一定的规则组装,回复给公众账号,公众账号再回复给用户,在这个收发过程中,发送方和接收方进行了调换(ToUserName和FromUserName值互换),收发都是以xml格式在后台进行传输的,

所以掌握各种消息类型的接收回复就是进行微信公众平台开发的基础!

下面对前面所述的各种消息类型讲解其XML数据包的格式。

 

各种收发消息的XML数据包分析

接收消息

1. 文本(包括表情)
接收文本及表情

文字后台格式:

<xml>
 <ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
 <FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
 <CreateTime>1359028446</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[测试文字]]></Content>
 <MsgId>5836982729904121631</MsgId>
</xml>

表情后台格式

<xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359044526</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[/::)/::~/::B/::|/:8-)]]></Content>
<MsgId>5837051792978241864</MsgId>
</xml>

XML格式讲解

ToUserName 消息接收方微信号,一般为公众平台账号微信号
FromUserName 消息发送方微信号
CreateTime 消息创建时间
MsgType 消息类型;文本消息为text
Content 消息内容
MsgId 消息ID号

可以看出,文本和表情的消息类型均为文本

2. 图片
接收图片

后台格式:

<xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359028479</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<PicUrl><![CDATA[http://mmbiz.qpic.cn/mmbiz/L4qjYtOibummHn90t1mnaibYiaR8ljyicF3MW7XX3BLp1qZgUb7CtZ0DxqYFI4uAQH1FWs3hUicpibjF0pOqLEQyDMlg/0]]></PicUrl>
<MsgId>5836982871638042400</MsgId>
<MediaId><![CDATA[PGKsO3LAgbVTsFYO7FGu51KUYa07D0C_Nozz2fn1z6VYtHOsF59PTFl0vagGxkVH]]></MediaId>
</xml>

XML格式讲解

ToUserName 消息接收方微信号,一般为公众平台账号微信号
FromUserName 消息发送方微信号
CreateTime 消息创建时间
MsgType 消息类型;图片消息为image
PicUrl 图片链接地址,可以用HTTP GET获取
MsgId 消息ID号

3. 语音
接收语音

后台格式:

<xml>
    <ToUserName><![CDATA[gh_d035bb259cf5]]></ToUserName>
    <FromUserName><![CDATA[owEUGj4BW8yeWRvyEERiVGKwAF1Q]]></FromUserName>
    <CreateTime>1364883809</CreateTime>
    <MsgType><![CDATA[voice]]></MsgType>
    <MediaId><![CDATA[JfmCezZ3Cwp0FwUvMADwwhvp-XScuvpictubpw0c6ALyA8tj3HLU4PoXzMpIY72P]]></MediaId>
    <Format><![CDATA[amr]]></Format>
    <MsgId>5862131322594912688</MsgId>
</xml>

XML格式讲解

ToUserName 消息接收方微信号,一般为公众平台账号微信号
FromUserName 消息发送方微信号
CreateTime 消息创建时间
MsgType 消息类型;语音消息为voice
MediaId 媒体ID
Format 语音格式,这里为amr
MsgId 消息ID号
附:AMR接口简介
全称Adaptive Multi-Rate,主要用于移动设备的音频,压缩比比较大,但相对其他的压缩格式质量比较差,由于多用于人声,通话,效果还是很不错的。

4. 视频

接收视频

后台格式:

xml><ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359028186</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
<MediaId><![CDATA[DBVFRIj29LB2hxuYpc0R6VLyxwgyCHZPbRj_IIs6YaGhutyXUKtFSDcSCPeoqUYr]]></MediaId>
<ThumbMediaId><![CDATA[mxUJ5gcCeesJwx2T9qsk62YzIclCP_HnRdfTQcojlPeT2G9Q3d22UkSLyBFLZ01J]]></ThumbMediaId>
<MsgId>5836981613212624665</MsgId>
</xml>

XML格式讲解

ToUserName 消息接收方微信号,一般为公众平台账号微信号
FromUserName 消息发送方微信号
CreateTime 消息创建时间
MsgType 消息类型;视频消息为video
MediaId 媒体ID
ThumbMediaId 媒体缩略ID?
MsgId 消息ID号

5. 位置

接收位置

后台格式:

<xml>
<ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
<FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
<CreateTime>1359036619</CreateTime>
<MsgType><![CDATA[location]]></MsgType>
<Location_X>22.539968</Location_X>
<Location_Y>113.954980</Location_Y>
<Scale>16</Scale>
<Label><![CDATA[中国广东省深圳市南山区华侨城深南大道9789号 邮政编码: 518057]]></Label>
<MsgId>5837017832671832047</MsgId>
</xml>

XML格式讲解

 ToUserName 消息接收方微信号,一般为公众平台账号微信号
 FromUserName 消息发送方微信号
 CreateTime 消息创建时间
 MsgType 消息类型,地理位置为location
 Location_X 地理位置纬度
 Location_Y 地理位置经度
 Scale 地图缩放大小
 Label 地理位置信息
 MsgId 消息ID号

6. 链接

接收链接

后台格式:

<xml>
<ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName> 
<FromUserName><![CDATA[oIDrpjl2LYdfTAM-oxDgB4XZcnc8]]></FromUserName> 
<CreateTime>1359709372</CreateTime> 
<MsgType><![CDATA[link]]></MsgType> 
<Title><![CDATA[微信公众平台开发者的江湖]]></Title> 
<Description><![CDATA[陈坤的微信公众号这段时间大火,大家..]]></Description> 
<Url><![CDATA[http://israel.duapp.com/web/photo.php]]></Url> 
<MsgId>5839907284805129867</MsgId> 
</xml> 

XML格式讲解

 ToUserName 消息接收方微信号,一般为公众平台账号微信号
 FromUserName 消息发送方微信号
 CreateTime 消息创建时间
 MsgType 消息类型,链接为link
 Title 图文消息标题
 Description 图文消息描述
 Url 点击图文消息跳转链接
 MsgId 消息ID号

 

回复消息

只介绍三种格式的消息:文本、图文、音乐。其中图文消息包括单条图文消息和多条图文消息,展示方式有一点点不同。

1. 文本消息格式
回复文本

后台格式:

<xml>
<ToUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></ToUserName>
<FromUserName><![CDATA[gh_680bdefc8c5d]]></FromUserName>
<CreateTime>1359036631</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[【深圳】天气实况 温度:27℃ 湿度:59% 风速:东北风3级
11月03日 周日 27℃~23℃ 小雨 东北风4-5级
11月04日 周一 26℃~21℃ 阵雨 微风
11月05日 周二 27℃~22℃ 阴 微风]]></Content>
<FuncFlag>0</FuncFlag>
</xml>

XML格式讲解

 FromUserName 消息发送方
 ToUserName 消息接收方
 CreateTime 消息创建时间
 MsgType 消息类型,文本消息必须填写text
 Content 消息内容,大小限制在2048字节,字段为空为不合法请求
 FuncFlag 星标字段

 
2. 图文消息格式
2.1 单条图文消息
回复单条图文


后台格式:

<xml>
    <ToUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></ToUserName>
    <FromUserName><![CDATA[gh_680bdefc8c5d]]></FromUserName>
    <CreateTime>1359011899</CreateTime>
    <MsgType><![CDATA[news]]></MsgType>
    <Content><![CDATA[]]></Content>
    <ArticleCount>1</ArticleCount>
    <Articles>
        <item>
            <Title><![CDATA[[苹果产品信息查询]]></Title>
            <Description><![CDATA[序列号:USE IMEI NUMBER
IMEI号:358031058974471
设备名称:iPhone 5C
设备颜色:
设备容量:
激活状态:已激活
电话支持:未过期[2014-01-13]
硬件保修:未过期[2014-10-14]
生产工厂:中国]]>
    </Description>
            <PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/banner.jpg]]></PicUrl>
            <Url><![CDATA[]]></Url>
        </item>
    </Articles>
    <FuncFlag>0</FuncFlag>
</xml>

2.2 多图文消息

回复多图文

后台数据格式

<xml>
    <ToUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></ToUserName>
    <FromUserName><![CDATA[gh_680bdefc8c5d]]></FromUserName>
    <CreateTime>1359011829</CreateTime>
    <MsgType><![CDATA[news]]></MsgType>
    <Content><![CDATA[]]></Content>
    <ArticleCount>5</ArticleCount>
    <Articles>
        <item>
            <Title><![CDATA[【深圳】天气实况 温度:3℃ 湿度:43﹪ 风速:西南风2级]]></Title>
            <Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/banner.jpg]]></PicUrl>
            <Url><![CDATA[]]></Url>
        </item>
        <item>
            <Title><![CDATA[06月24日 周四 2℃~-7℃ 晴 北风3-4级转东南风小于3级]]></Title>
            <Description><![CDATA[]]></Description>
            <PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d00.gif]]></PicUrl>
            <Url><![CDATA[]]></Url>
        </item>
        <item>
            <Title><![CDATA[06月25日 周五 -1℃~-8℃ 晴 东南风小于3级转东北风3-4级]]></Title>
            <Description><![CDATA[]]></Description>
    <PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d00.gif]]></PicUrl>
            <Url><![CDATA[]]></Url>
        </item>
        <item>
            <Title><![CDATA[06月26日 周六 -1℃~-7℃ 多云 东北风3-4级转东南风小于3级]]></Title>
            <Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d01.gif]]></PicUrl>
            <Url><![CDATA[]]></Url>
        </item>
        <item>
            <Title><![CDATA[06月27日 周日 0℃~-6℃ 多云 东南风小于3级转东北风3-4级]]></Title>
            <Description><![CDATA[]]></Description>
<PicUrl><![CDATA[http://www.doucube.com/weixin/weather/icon/d01.gif]]></PicUrl>
            <Url><![CDATA[]]></Url>
        </item>
    </Articles>
    <FuncFlag>0</FuncFlag>
</xml>

XML格式讲解

FromUserName 消息发送方
 ToUserName 消息接收方
 CreateTime 消息创建时间
 MsgType 消息类型,图文消息必须填写news
 Content 消息内容,图文消息可填空
 ArticleCount 图文消息个数,限制为10条以内
 Articles 多条图文消息信息,默认第一个item为大图
  Title 图文消息标题
  Description 图文消息描述
  PicUrl 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80
  Url 点击图文消息跳转链接
FuncFlag 星标字段

 3. 音乐消息

回复音乐消息

后台格式:

<xml>
    <ToUserName><![CDATA[ollB4jqgdO_cRnVXk_wRnSywgtQ8]]></ToUserName>
    <FromUserName><![CDATA[gh_b629c48b653e]]></FromUserName>
    <CreateTime>1372310544</CreateTime>
    <MsgType><![CDATA[music]]></MsgType>
    <Music>
        <Title><![CDATA[最炫民族风]]></Title>
        <Description><![CDATA[凤凰传奇]]></Description>
        <MusicUrl><![CDATA[http://zj189.cn/zj/download/music/zxmzf.mp3]]></MusicUrl>
        <HQMusicUrl><![CDATA[http://zj189.cn/zj/download/music/zxmzf.mp3]]></HQMusicUrl>
    </Music>
    <FuncFlag>0</FuncFlag>
</xml>

XML格式讲解

ToUserName     接收方帐号(收到的OpenID)
FromUserName     开发者微信号
CreateTime     消息创建时间
MsgType          消息类型,此处为music
    Title       音乐标题
    Description 音乐描述
    MusicUrl     音乐链接
    HQMusicUrl     高质量音乐链接,WIFI环境优先使用该链接播放音乐
FuncFlag     位0x0001被标志时,星标刚收到的消息。

 

事件消息类型

目前用户在关注和取消关注,以及点击菜单的时候会自动向公众平台发送事件推送消息:

1. 关注事件

<xml>
    <ToUserName><![CDATA[gh_b629c48b653e]]></ToUserName>
    <FromUserName><![CDATA[ollB4jv7LA3tydjviJp5V9qTU_kA]]></FromUserName>
    <CreateTime>1372307736</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
    <EventKey><![CDATA[]]></EventKey>
</xml>

2. 取消关注事件

<xml>
    <ToUserName><![CDATA[gh_b629c48b653e]]></ToUserName>
    <FromUserName><![CDATA[ollB4jqgdO_cRnVXk_wRnSywgtQ8]]></FromUserName>
    <CreateTime>1372309890</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[unsubscribe]]></Event>
    <EventKey><![CDATA[]]></EventKey>
</xml>

3. 菜单点击事件

<xml>
    <ToUserName><![CDATA[gh_680bdefc8c5d]]></ToUserName>
    <FromUserName><![CDATA[oIDrpjqASyTPnxRmpS9O_ruZGsfk]]></FromUserName>
    <CreateTime>1377886191</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[CLICK]]></Event>
    <EventKey><![CDATA[天气深圳]]></EventKey>
</xml>

XML格式讲解

ToUserName     接收方微信号
FromUserName 发送方微信号,若为普通用户,则是一个OpenID
CreateTime     消息创建时间
MsgType     消息类型,event
Event     事件类型,subscribe(订阅)、unsubscribe(取消订阅)、CLICK(自定义菜单点击事件)
EventKey 事件KEY值,与自定义菜单接口中KEY值对应

 

 

 第四章 实现天气预报功能

 

这一章里,我们来实现微信上的天气预报功能,我们使用方倍工作室的天气预报接口,其接口为

http://apix.sinaapp.com/weather/

这个接口的参数appkey为公众号原始id,参数city为城市名

例如,查询深圳的天气预报时,将city值做urlencode,最终访问的url为

http://apix.sinaapp.com/weather/?appkey=trialuser&city=%E6%B7%B1%E5%9C%B3

返回的内容如下

[
    {
        "Title": "深圳天气预报",
        "Description": "",
        "PicUrl": "",
        "Url": ""
    },
    {
        "Title": "【实况】温度18℃ 湿度59%% 东北风2级 发布时间:08:55",
        "Description": "",
        "PicUrl": "",
        "Url": ""
    },
    {
        "Title": "【舒适】建议着长袖T恤、衬衫加单裤等服装。年老体弱者宜着针织长袖衬衫、马甲和长裤。",
        "Description": "",
        "PicUrl": "",
        "Url": ""
    },
    {
        "Title": "11月19日 周三 晴 23℃~17℃ 无持续风向 微风 日出日落:06:38~17:39",
        "Description": "",
        "PicUrl": "http://discuz.comli.com/weixin/weather/icon/d00.jpg",
        "Url": ""
    },
    {
        "Title": "11月20日 周四 多云 25℃~17℃ 无持续风向 微风 日出日落:06:39~17:38",
        "Description": "",
        "PicUrl": "http://discuz.comli.com/weixin/weather/icon/d01.jpg",
        "Url": ""
    },
    {
        "Title": "11月21日 周五 多云 26℃~18℃ 无持续风向 微风 日出日落:06:40~17:38",
        "Description": "",
        "PicUrl": "http://discuz.comli.com/weixin/weather/icon/d01.jpg",
        "Url": ""
    }
]

我们在微信中调用这一接口来获取天气预报信息,实现代码如下

<?php
/*
    方倍工作室
    CopyRight 2014 All Rights Reserved
*/

define("TOKEN", "weixin");

$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
    $wechatObj->responseMsg();
}else{
    $wechatObj->valid();
}

class wechatCallbackapiTest
{
    //验证签名
    public function valid()
    {
        $echoStr = $_GET["echostr"];
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        if($tmpStr == $signature){
            echo $echoStr;
            exit;
        }
    }

    public function responseMsg()
    {
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        if (!empty($postStr)){
            $this->logger("R ".$postStr);
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);

            $result = "";
            switch ($RX_TYPE)
            {
                case "event":
                    $result = $this->receiveEvent($postObj);
                    break;
                case "text":
                    $result = $this->receiveText($postObj);
                    break;
            }
            $this->logger("T ".$result);
            echo $result;
        }else {
            echo "";
            exit;
        }
    }

    private function receiveEvent($object)
    {
        switch ($object->Event)
        {
            case "subscribe":
                $content = "欢迎关注方倍工作室 ";
                break;
        }
        $result = $this->transmitText($object, $content);
        return $result;
    }

    private function receiveText($object)
    {
        $keyword = trim($object->Content);
        $url = "http://apix.sinaapp.com/weather/?appkey=".$object->ToUserName."&city=".urlencode($keyword); 
        $output = file_get_contents($url);
        $content = json_decode($output, true);

        $result = $this->transmitNews($object, $content);
        return $result;
    }

    private function transmitText($object, $content)
    {
        if (!isset($content) || empty($content)){
            return "";
        }
        $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
        $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
        return $result;
    }

    private function transmitNews($object, $newsArray)
    {
        if(!is_array($newsArray)){
            return "";
        }
        $itemTpl = "    <item>
        <Title><![CDATA[%s]]></Title>
        <Description><![CDATA[%s]]></Description>
        <PicUrl><![CDATA[%s]]></PicUrl>
        <Url><![CDATA[%s]]></Url>
    </item>
";
        $item_str = "";
        foreach ($newsArray as $item){
            $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
        }
        $newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";

        $result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray));
        return $result;
    }

    private function logger($log_content)
    {
      
    }
}
?>

上述代码的下载地址为 http://pan.baidu.com/s/1gdsyHWJ,同样的方法,可将代码上传到SAE上。

在公众账号中使用的命令如下:

  1. 发送城市名称,如“深圳”,可以查询该城市的天气

在你的公众账号输入相应的命令,实现效果类似如下所示:

 

第五章 小结

 

总的来说,通过本教程,你得到了以下收获:

  • 1. 你通过本教程得到了一个免费的新浪云计算空间,云计算哦
  • 2. 你成功启用了开发模式,并且实现了时间的自动回复
  • 3. 你了解了微信公众平台开发的原理,并且熟悉了各种消息及发送是怎么一回事
  • 4. 你使用方倍工作室的天气预报接口,实现了一个微信公众平台上的天气预报功能。

接下来该做什么呢?你可以学习开发一些基础的常用功能,推荐:方倍工作室 编写,机械工业出版社 出版的《微信公众平台开发最佳实践 第2版》,里面包含很多php开发技巧、数据库使用、及近30项微信公众平台实用功能或技术 。 

点击图标购买:

 

 

学习完这一层次之后,你可以开始自己胜任一个中小型的微信公众平台账号功能的开发了。

如果你没有PHP及Mysql方面的开发基础,我们也建议你购买《PHP和MySQL Web开发(原书第4版)》,该书被评为“PHP和MySQL程序员的最佳参考书”,

点击图标购买

 

捐赠我们
方倍工作室一直在致力于帮助开发人员更加快速方便的进行微信公众平台的开发,如果您对我们的成果表示认同并且觉得对你有所帮助,欢迎您对我们捐赠^_^。

 

 原文:http://www.cnblogs.com/txw1958/p/wechat-tutorial.html 

 

作者:txw1958 发表于 2016/01/16 11:33:05 原文链接 https://blog.csdn.net/txw1958/article/details/50527404

阅读:1942

 
[原]微信web开发者工具
 

概述

为帮助开发者更方便、更安全地开发和调试基于微信的网页,我们推出了 web 开发者工具。它是一个桌面应用,通过模拟微信客户端的表现,使得开发者可以使用这个工具方便地在 PC 或者 Mac 上进行开发和调试工作。立即下载体验

你可以:

  • 使用自己的微信号来调试微信网页授权
  • 调试、检验页面的 JS-SDK 相关功能与权限,模拟大部分 SDK 的输入和输出
  • 使用基于 weinre 的移动调试功能
  • 利用集成的 Chrome DevTools 协助开发

该工具界面主要由几大部分组成,如下图所示:

Tools_001.jpg

顶部菜单栏是刷新、后退、选中地址栏等动作的统一入口,以及微信客户端版本的模拟设置页。左侧是微信的 webview 模拟器,可以直接操作网页,模拟用户真实行为。右侧上方是地址栏,用于输入待调试的页面链接,以及清除缓存按钮。右侧下方是相关的请求和返回结果,以及调试界面和登录按钮。

调试微信网页授权

之前在开发基于微信的网页授权的功能时,开发者通常需要手机上输入 URL 进而获取用户信息,从而进行开发和调试工作,可是因为手机的诸多限制,这个过程很不方便。 通过使用微信 web 开发者工具,从此开发者可以直接在 PC 或者 Mac 上进行这种调试了。具体操作步骤为:

  • 开发者可以在调试器中点击“登录”,使用手机微信扫码登录,从而使用真实的用户身份来开发和调试微信网页授权。请确认手机登录页,绑定的公众号为“微信 web 开发者工具”,如下图所示:

Tools_006.jpg

  • 为了保证开发者身份信息的安全,对于希望调试的公众号,我们要求开发者微信号与之建立绑定关系。具体操作为:公众号登录管理后台,启用开发者中心,在开发者工具——web 开发者工具页面,向开发者微信号发送绑定邀请。绑定页面如下图所示:

Tools_002.jpg

  • 开发者在手机微信上接受邀请,即可完成绑定。每个公众号最多可同时绑定10个开发者微信号。邀请确认页面如下图所示:

Tools_003.jpg

  • 完成登录和绑定后,开发者就可以开始调试微信网页授权了:

非静默授权的 URL: https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx841a97238d9e17b2&redirect_uri=http://cps.dianping.com/weiXinRedirect&response_type=code&scope=snsapi_userinfo&state=type%3Dquan%2Curl%3Dhttp%3A%2F%2Fmm.dianping.com%2Fweixin%2Faccount%2Fhome

在微信 web 开发者工具中打开这个 URL,webview 模拟器显示效果如图:

Web-developer-tools-02.jpg

点击“确认登录”即可带着用户信息跳转到第三方页面,很方便的进行后续的开发和调试。

静默授权的 URL: https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx841a97238d9e17b2&redirect_uri=http://cps.dianping.com/weiXinRedirect&response_type=code&scope=snsapi_base&state=type%3Dquan%2Curl%3Dhttp%3A%2F%2Fmm.dianping.com%2Fweixin%2Faccount%2Fhome

在微信 web 开发者工具中打开该 URL 则会自动跳转到第三方页面。

 

模拟JSSDK权限校验

通过 web 开发者工具,可以模拟 JSSDK 在微信客户端中的请求,并直观地看到鉴权结果和 log。以微信 JSSDK DEMO 页面为例:

http://demo.open.weixin.qq.com/jssdk

在调试器中打开该 URL,可以方便地在右侧的 JS-SDK Tab 中看到当前页面 wx.config 的校验情况和 JSSDK 的调用 log。 如下是校验通过的页面:

Web-developer-tools-03.jpg

如下是校验未通过的页面:

Tools_004.jpg

在“权限列表” Tab 中,可以查询到当前页面拥有权限的 JS-SDK 列表:

Web-developer-tools-04.jpg

移动调试

移动调试功能是基于 weinre 的,并且做了一些改进,相比直接使用 weinre 有两个优点:

  • 无须手工在页面中加入 weinre 调试脚本
  • 可以在 weinre 的网络请求页卡中,看到完整的 http 请求 log,非局限于 ajax 请求

如下图所示:

Web-developer-tools-08.jpg

 

Chrome DevTools

微信 web 开发者工具集成了 Chrome DevTools。同之前在 PC 上的调试体验一致,可以快速上手。

如下图所示:

Web-developer-tools-09.jpg

 

下载地址

最新版本: (2016.01.11) 0.1.0

Windows 64位版本:下载地址

 MD5: 04cf4723256b82a284c008bd76b4c67d

Windows 32位版本:下载地址

 MD5: 64f21471fcb10cededfb07b5174a7d02

Mac版本:下载地址

 MD5: 761465844c55d4c61a001d668578f84a

 

技术支持与反馈

邮箱地址:weixin-open@qq.com

邮件主题:【微信web开发者工具反馈】

邮件内容说明:

用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。

 

作者:txw1958 发表于 2016/01/16 11:33:02 原文链接 https://blog.csdn.net/txw1958/article/details/50527403

阅读:1012

 
[原]张小龙首次公开演讲(官方无删减版)
2016-01-11 微信公开课

 

大家早上好,我是微信的张小龙。

 

从昨晚的传播事件说起,为什么微信在很多的规则、平台接口或者系统方面很严格?

 

可能会有一些朋友觉得比较突然,我也是比较突然进来参加这样一个会议,很高兴在这里跟大家碰面。平时我很少参加会议,可能很多人都搞不懂,其实我们同事都知道,我一直有一个观点:在一个移动互联网非常发达的时代,参加会议是挺浪费时间的。所以一般我也跟我们同事说尽可能的少去参加一些会议,但我不是说大家来参加这个会议浪费时间,我觉得这个时间还是挺宝贵的。

 

其实会议本身不会浪费时间,但对于微信来说,我们会同时面对几亿用户,我们会觉得应该把更多的时间聚焦在用户身上。以微信的体量来说,我们直接面对的可能是上亿用户的一些事情的发生,比如说一些传播。

 

平台遵循严格的规则设置接口

 

我们刚刚经历了一次特别大的传播事件。昨天晚上,可能在座的很多人都在朋友圈里晒出了自己的第一个好友,发了多少红包这样一个数据,这个数据其实在昨天晚上把我们给忙坏了,我们说它是一次蝴蝶效应,一个非常典型的传播事件。可能大家没有想到,只是晒一下朋友圈这样一个“微信公开课”活动,却导致了一连串事情的发生。

 

我们昨晚看到这样一个活动页面被人在朋友圈里晒出来,这个活动其实它的意图只是说在活动现场大家来签一下到,现场的人可以访问这样一个数据,去晒到朋友圈。昨天这个链接就被泄漏了,被更多的人去点,然后就去传,这样就带来了第一个问题:这个链接访问太高,几乎是挂掉了。几乎挂掉以后就会带来第二个问题:就有人开始造谣了,打开这个链接就会把你支付宝的钱给偷了。很多人就信了,为什么呢?因为很多人再点进去发现打不开了。这个时候又发生了再后面的一件事情:我们支付的同事就发现很多的用户,甚至开始解绑自己的银行卡了

 

那是不是真的被盗了?然后我们内部就很着急,就来处理这样一个事情。以前我们都知道有一个效应叫“蝴蝶效应”,说一只蝴蝶在一个地方煽动翅膀,可能在纽约引起一场风暴。以前我们觉得很难在身边发生的一个事情,昨天晚上大概短短一两个小时它就真的发生了,并且出乎我们做这个活动同事的预料。所以刚刚我们跟公关部门的同事在讨论说,他们是不是开完这个会就解散了,我说,不用那么快。因为蝴蝶效应本身来说是很难遇到的,但是在微信这样一个平台上面,它真的是瞬间就会发生。

 

我用这个作为开头,其实是想跟大家说明一个事情,微信作为一个平台,为什么我们在很多的规则,很多的平台接口或者系统方面会很严格,是因为其实有一点小小的疏漏可能就会在这个平台里面被放大很多很多次,这个量级是很可怕的。

 

后来我们会有很多同事介绍微信平台各个方面的事情,我今天过来其实有一个想法是觉得,包括在座的各位都是有非常多的疑问,这些疑问其实我们很难一一去解答,而且我们的平台规则也在不断的演化。很多人会说,为什么你们的平台会变来变去?你们的规则为什么总是不清晰?为什么不能明确一点给我们写出来?很抱歉,我们确实给不出一个特别明确的东西,因为我们自己也是在变化,我特别想借这个机会跟大家分享的是,我们最底层的一个思考,就是我们对待我们的产品和平台,我们的自己价值观是什么样的?我们知道做一个事情有很多很多方法去做到,做一个产品也是这样子,但是大家会做出不同的结果,除了大家用的方法不一样以外,其实有一个最底层的东西,就是你看待这个事情,你看待你产品的价值观来决定的,你是一个什么样的价值观决定了你会做一个什么样的东西出来。我今天想跟大家分享的是,微信对于产品和我们的平台的价值观,如果大家能理解我们的价值观,那我相信你在做微信相关事情的时候,你会知道你做的事情会不会被我们拦截或者是我们鼓励的。

 

 

一切以用户价值为依归

 

在这块,我想分享四个方面的价值观:

 

第一点,我说出来,在座可能腾讯的同事都首先熟悉这句话,这是腾讯公司里面一直在强调的价值观,就是一切以用户价值为依归,用户价值是第一位的,这句话看起来像老生常谈或者很普通,但是我要说的是,其实这句话让一个好的产品和一个坏的产品拉开了差距,大家都明白用户很重要,但真正把用户价值第一做到产品里面去的不多,大部分只是把这个作为一句口头禅在说,但是在微信和微信的平台里面,我们把这个作为第一要事,作为最重要的一个因素。很多人是没有真正明白这一句话的,比如说给大家一个机会,说微信这里有一些特别的接口或者特别的权限给各位,都一定会很开心。很多公司内部或者外部找我们合作,为了合作大部分都是一个交换说我有什么资源,你有什么资源,我们来交换一下,这就是合作,但是所有的合作里面都会把用户价值放在最末端,因为你首先考虑的是一个资源的交换,所以我们不会跟任何的,包括外部的、内部的去做这种资源的交换取代用户价值的情况,当我们面对一个合作的时候,我们首先会考虑的是这样一个合作对于用户是不是有价值的,是不是用户所需要的,如果我们这样作为一个最基础的考量点,我们自然就会有很多的合作,很多的决策,做出一些判断,我们就会直接打掉很多没有必要的行为,对微信和微信平台来说,我们现在更多的挑战不是在于说我们再多做多少事情,而是我们能够挡掉多少事情。

 

从平台的角度来说,我们更希望的是我们平台会提供无限种可能性给第三方去开发,而不是说我们一单一单的去谈很多的合作回来,甚至这个合作对用户是毫无价值的。各位用微信的应该会体现这一点,会感受到其实微信一直在很小心翼翼保护你用微信的体验,你不会在微信里面看到突然有一个什么样的群发过来,突然有一些系统上的消息过来,你觉得这是很习以为常的,但是从我们看过来,其实是需要做很多事情才能让微信里面的内容非常干净,从一个业务推广的角度来说,我们公司内部也会有非常多的业务,在微信里面群发一条就可以帮助什么,但是微信里面不会有这样的结果。

 

对外部来说,其实我们更希望的是平台有一些公平、公正的一些规则来对待用户,所以基本上大家都会看到,微信这里会提供出一些特权出来,例如说很多朋友会跟我们说,我能不能让自己的好友数超过5000人,我说这个没有可能,因为系统里面就没有超过5000人的号,我的观点是白名单是一个系统的瑕疵。有一些朋友也会跟我们提需求说,能不能给我们开一个白名单,把微信红包的金额提高一下,因为我是一个土豪,我想给别人发800块的红包,开一个白名单对我们来说是举手之劳,对我们的客人来说会觉得这是与众不同的权限,可以炫耀一把,我们确实开过这样的白名单,但是前不久我们把它关闭了,因为我们发现如果开一个白名单出去,我们只会在用户里面造成一种攀比,造成一种不均衡,而这样的现象不是我们倡导的微信文化。系统要做这个事情只有两个方法:一是没有特权的白名单;二是如果这个需求普遍,就是有很多人有很强的需求,那么系统应该有一个规则来释放这个需求,而不是通过找关系或者是白名单这样的方式来满足少数人的需求,这不在我们产品鼓励的方向中。

 

这是关于用户的价值,这里可以举很多例子,又比如说很多的公众号可能把拉粉作为他最大的一个诉求,但你会看到其实微信里面几乎没有地方可以提供你可以很轻易的获取粉丝。这里要考虑一点,你吸引到了非常多的粉丝,这些粉丝真的是愿意被你吸引才过来的,这个区分很重要,如果是被你用各种手段牵过来的粉丝,这是没有意义的,也违背了我们以用户第一为价值观点的考量。假设一个公众号有1000万粉丝,可是这是在用户不太知情的情况底下获得的,可能很危险。为什么很危险?举一个例子,我们有一些号有很多粉丝,他不敢发消息,因为他一发消息就掉粉。大家可以再想象一下,假设用户对这样的号不喜欢,不断骚扰他的意见越来越大。微信里可能会出一个功能,其实对用户说一下这个号3个月没有访问了,是不是可以退订了,那就可以退订了,这样的话对更大的号反而是一个更大的损失,但是从用户层面,这是真正的用户价值。所以在微信里面我们一直说绝不允许骚扰用户,绝不允许把用户不需要的东西推给用户。

 

这是我今天分享的第一点,如果大家在做微信相关的项目,你会有很多的选择时,不妨也从这个角度来思考一下它是不是符合微信价值的价值观。

 

关于用户价值,我有一天分享过亚马逊CEO的一个文章,他的文章标题叫做《善良比聪明更重要》。我相信在座的人都是很聪明的人,因为大家会想到很多很多的方法去欺骗用户,欺骗用户是最容易做的事情,因为只需要聪明就可以了,这是不对的,因为欺骗用户虽然很容易获得流量,可以获得用户的点击,但是最终会把用户给赶跑了。所以这篇文章写的非常好,善良比聪明更重要,怎么样对用户是好的——这个会聪明会更重要一些。

 

 

让创造发挥价值

 

什么是让创造发挥价值?围绕公众平台来说的话,公众平台从它的诞生到现在,大家一直觉得这是一个开放平台,我们利用这个平台可以获得粉丝,可以做营销,可以做推广,但是可能很少会想什么是公众平台的价值观。

 

公众平台到底想要变成什么?公众平台从它诞生的第一天起,公众平台的目标是要让真正有价值的东西发挥出它的价值。什么是有价值的东西?在非互联网的时代,有价值的人或者是一个团队,即使做了一个很有价值的事情,也很难去触达用户。

 

但是这样的情况不应该出现在目前这个时代。所以大家有一个很强的愿望,既然有非常多的用户,我们就应该提供一个平台,让所有有才能的人都能利用这个平台去触达他的用户。这个有才能的人不是说只是互联网行业的人,而应该是各行各业的人,所以我们经常用一个比方来说:要让一个盲人在一个楼里给人按摩,他也能获得一个稳定的客户群,这是信息不发达的时候,对于地域,对于传统一些物理条件限制的突破所带来的好处。

 

所以从公众平台秉持的目标来说,我们是希望让这个平台里面涌现出更多的有创造力的事情出来,而不是说这个平台就是一个做流量的地方、大家可以在这个地方导流量,不是这样子的。这里我们是希望所有围绕微信开发的第三方都能想一个问题,你到底是想要用这个平台来做什么,是想要给你的用户提供一些有价值的服务,还是只是想利用它做一个流量的导流?如果只是做一个流量的导流,那不是平台所愿意看到的。不管平台的规则怎么样变化,只有有创造性的东西、有价值的东西才是微信所倡导的,不管平台有什么变化,大家都不用担心我做的事情会不会被平台封杀。

 

我们去年花了很多时间去扶持原创。原创是一个非常好的事情,但是在过去一段时间,从BBS到博客时代,很多文章写的特别好的人在互联网上其实是很难得到价值回报,如果是这样的话,这个市场环境就会恶劣,劣币驱逐良币。所以我们花了很多时间把原创作为一个非常认真的事情去做,关于版权的保护、内容的保护,使得在过去一年里面原创得到了非常大的发展。现在一个好的作者,他的一篇文章写出来可能会吸引上万的一个赞赏的回报,当然这只是非常小的一个回报。我们认为原创的文章更符合我们需要的价值,也更符合用户的价值,所以,为了扶持原创,对于原创文章里面的广告条,对广告分成也特别优惠,因为原创的流量不会特别大。平台里面我们发现这样一点,流量大的未必是好的,比如像昨天那种谣言传播的流量就非常大,所以真正有价值的东西未必能获得巨大的流量,所以从平台角度我们会去扶持它。

 

所以关于要创造几项价值,刚才说到我们原创号这里,可能在座还会有很多的人会说,我不是写文章的,我可能写不出好的文章,我其实只是想提供服务,后面我会讲到会有一个新的东西,在后面再跟大家分享一下。

 

好的产品应该是用完即走的

 

第三个,我想跟大家分享微信的一个基本价值观,我们认为一个好的产品是一个用完即走的,就是用完了我就走了,可能大家不是第一次听到这个词。一个好的产品不是黏住用户,而是尽量让这个用户离开你的产品,大家同意吗?说同意的都是没有认真思考的,因为我相信每个人做的工作都是围绕一点,怎么样黏住用户,怎么样让用户尽可能待在我的产品里头,不要离开产品。

 

我们认为任何产品都只是一个工具,对工具来说,好的工具就是应该最高效率的完成用户的目的,然后尽快的离开。如果一个用户要沉浸在里面,离不开,就像你买一辆汽车,你开完了,你到了目的地,你说汽车里面的空调特别好,所以要待在里面,那不是它应该做的事情。所以业界很羡慕微信是用户的时间杀手,但是我们要考虑的则是怎么样更高效率帮助用户完成任务,而不是让用户在微信里面永远都有处理不完的事情,所以大家会看到微信的朋友圈会限制很严,各种营销在朋友圈里面我们都会很严格的对待。我们刚开始看朋友圈里面都是一些朋友的动态,可是慢慢发现朋友圈里面有很多心灵鸡汤,被各种各样地诱导上来发了一些内容,如果这样的信息多了其实最终的结果未必好,最终的结果可能是用户觉得朋友圈里面的信息太水了、太杂了,慢慢他再看朋友圈的意愿越来越低,这会变得非常可怕。因为朋友圈的进入次数特别多,平均一个用户每天大概有30、40次进入朋友圈,这是一个反复的过程,我们希望每次进来用户都不是很快的刷屏,而是看到的都是他愿意看到的内容。

 

对于微信里面其他的功能其实也是如此。我们希望用户在用微信的时候,最高效率把必须要做的在微信里面做完,把时间留出来去做很多别的事情。在座的各位,基于微信来做一些项目的时候不妨也多从这个角度思考一下,你做的事情是在帮助用户节约他的时间,提高他的效率,还是说只是想让他在这里不断地消磨时间。如果你想要让他消磨时间,你可以写一篇文章再写一篇文章,用户永远都出不去,但是用户可能下一次就不敢再进来了。在这一方面做的好的例子,我觉得是谷歌,谷歌在很多年前就提出来让用户搜完就走。在这点上,我们会希望微信里面的信息尽可能的少,少到只能满足你最基本的需求,这样你就明白微信为什么会有这样一些规则。

 

举个例子来说,如果是很早期的微信用户就会发现,微信其实一直不鼓励你加太多好友,所有的加好友都要经过你的验证通过才会加进来,其实如果微信作为一个产品要让好友变得很多的话很简单,只要把QQ好友、手机通讯录导进来默认变成你的好友就好了。但是我们一直非常谨慎,一直希望用户的好友不要太多,所以每次加好友都提示用户是不是确定要添加他,从来没有说批量导入过,我们业界经常说少即是多,但其实这也会变成一句口头禅,因为没有人真正明白,更少的信息意味着用户可以更高效的处理,意味着他可以腾出更多的时间,意味着这个产品的未来会变得更大。

 

大家也会看到,我们对于下发消息也非常严格,很多人不理解为什么一天只能发一次,为什么不是一天两次,每次还要限定那么几条。从微信的产品角度来看,这是一个很基本的体验性的东西,但是在外界看过来,这是难以理解的,包括特别多的媒体人会说,一天一次真的是不太够,我们就希望发更多的内容给用户。那是因为更多的人都是从自己的角度说我发的越多越好,但是从来没有想过发得多是不是意味着用户更愿意看。所以大家也会看到,为什么我们会对一些诱导分享有拦截,因为所谓诱导分享就是你分享出去了、你获得了好处,但你的朋友并没有获得好处,你的朋友要忍受你发来的一个东西,这也是我们的一个基本原则。

 

让商业化存在于无形之中

 

 

第四个想要跟大家分享的观点是,我们应该尽可能让商业化存在于无形之中。

 

为什么要让商业化于无形?我们发现很多人比我们更着急微信的商业化,也不知道为什么。但是我们确实认为一个好的产品它的商业化和用户的价值、用户的体验是并不矛盾的。好的商业化应该是不骚扰用户,并且是只触达他需要触达的那一部分用户,可能有一些人不玩游戏,但是并不妨碍另一部分人去玩游戏,玩游戏从系统来说是一个很好的商业化的过程。同样大家也会看到微信朋友圈的广告,我们也很高兴的看到朋友圈广告经过了一年的时间,很多的用户还在期待能看到一个朋友圈广告,因为平常他很少看得到,当用户有这样的心理,我们会觉得这个事情是对的,因为用户不反感它,甚至有时候会比较期待。我昨天还看到一个视频广告,觉得挺好的,但是当时我在底下评论了一句,有点开玩笑说“货不对版”,因为朋友圈广告的内容和真正的尝试有点不太接得上,有点欺骗用户的嫌疑,但这是一个广告创意的事情。所以从微信来说,我们希望微信能做很好的商业化,但是它不是基于骚扰的、基于流量变现的商业化。所以你现在看不到的启动页弹一个广告出来,因为我们觉得这是一个比较低级的商业化的手段。而关于这一点,待会会有一个卡券系统的一个广告。在去年的时候,我们发了很多很多的优惠券下去,然后我们发现优惠券实际被使用率非常低,可能有超过90%都废掉了、没有被使用出来,这和现实里面其实是一样的。现实里面可能我们也会拿到很多优惠券,但是大部分都不会去用它,我们会认为这不是一种很好的解决方案。

 

可能有极少数的用户已经在微信里面用到了我们现在一种新的优惠券,这种优惠券来自于一个小故事,有一个朋友去丽江玩,他住了一个客栈,然后客栈的老板就跟他说,如果你介绍一个朋友再来住这个客栈,你的朋友会获得一个优惠,并且你自己也会获得一个小红包,这是一个很明显的基于社交关系来做的一个传递的工作,它特别生动,特别有说服力。

 

这个故事让我们很有启发,我们会尝试一种基于社交关系的优惠券,我们看之前很多做优惠券的都很难做出来,当一个优惠券本身太容易获得就没有价值了,因为你随时可以拿到。但是对微信来说,这个优惠券是一种基于朋友背书的优惠券,也就是说只有你的朋友去那里消费才能拿到那个券,他分享出来,你可以使用,这和刚才那个故事是完全对应的。我们把这样一个新的系统上线以后,发现核销率迅速就上去了,而商家也很高兴,因为这个真正帮他带来了新的用户。朋友也很高兴,因为他的优惠券没有被浪费掉,这是一个对几方都共赢的一个事情。

 

这里的重点其实是,它也是一个商业化的产品,但是它在对用户非常有价值的基础上来做,不是作为一个广告塞到这里的,是你的好友获得一个券分享给你的,这是很不一样的。

 

最后跟大家分享一下我们正在构思的一些东西。刚刚公众平台说到原创,其实很多人会觉得有一点郁闷,因为公众平台现在看起来确实更像是一个媒体化的平台,是对于自媒体、一些写作的或者一些传播内容的人特别有效。但是我们的公众平台,我们出发点不是仅仅针对媒体的,我自己也是很多年的程序员,我们觉得2016年我们应该做一些事情,面向开发的团体。

 

这个需求来自于哪里呢?我们自己也观察到发现越来越多的创业公司它做的第一个产品就是基于微信的公众号来做的,而不是去开发一个APP,因为一个APP的推广成本实在是太高了。相比来说,公众号能够实现大致同样的事情,并且也能获得它的用户,并且用户可以在微信里面获得的成本或者传播的速度会更好一些。

 

但是我们的本意并不是要做成一个只是传播内容的平台,我们一直说我们是要做一个提供服务的平台,所以后面我们甚至专门拆分出一个服务号出来,但是服务号还是没有达到我们的要求,说服务号可以在里面提供服务为主,所有的服务号还是基于一个诉求,这不是我们想看到的。现在我们将开发一个新的形态,叫做应用号。我们现在每换一部手机,手机里面的APP就要重新装,我相信大部分用户也是这样的。现在APP重复的安装率已经越来越低,但是有的时候你要找一个功能,你还得重新再安装一下这个APP。现在很多用户会在微信钱包里面买火车票,因为对一些不是很高频度的需求来说不需要再按一个安装,可是从公众号里面去装一个功能其实也不容易,我们希望存在一种新的公众号的形态,这种形态下面用户关注了一个公众号,就像安装了一个APP一样,他要找这个公众号的时候就像找一个APP一样,进去使用这个公众号,在平时这个号不会向用户发东西的,所以APP就会很安静的存在那里,等用户需要的时候找到它就好了,这样的话我们可以尝试做到让更多的APP有一种更轻量的形态,但是又更好使用的一种形态来存在,这是我们在探讨的一种新的公众号形态,叫应用号,这里只是提前剧透一点点东西。

 

今天真的非常感谢大家能在这个现场参加这个会议,也非常抱歉,确实我个人不太喜欢参加会,我认为将来的会议是五年以后大家戴一个眼镜,坐在家里看跟在现场看是一样的效果,我很期待那一天。非常感谢大家,我今天的分享就到这里。

作者:txw1958 发表于 2016/01/16 11:33:00 原文链接 https://blog.csdn.net/txw1958/article/details/50527400

阅读:1067

 
[原]微信电话
微信电话是微信推出的网络电话功能,支持从微信以极低的费率直接拨打全球200多个国家或地区的手机和固定电话。该功能目前对美国、香港、印度用户开放,部分地区正在测试当中,未来将会有更多国家的用户可以使用。

  近日,有 Google+ 网友发现自己在使用的微信中新增了一个名为「微信电话」的新功能。这一功能提供了一个拨号盘,可以直接通过微信发起主叫电话。这一服务被叫方无需是微信用户,也不要求主叫被叫双方在有网络连接,与现在手机 QQ 和微信内置的语音通话不同,是一款基于 VoIP 的通话产品。

  在充值界面会发现该服务目前以美元计费,点击充值按钮之后会弹出 Google Play 充值界面,打往中国的主教电话资费为每 0.99 美元 110 分钟,折合人民币约为 6 分钱每分钟十分划算。

  在关于微信电话的页面中,我们看到这一服务目前还正在测试期目前仅对美国、香港、印度用户开放,但这些地区的用户可以用极低的费率拨打全球 200 多个国家和地区的手机和固定电话。

  遗憾的是,目前国内的普通用户尚不能使用该服务,目前推测要使用该功能需要同时满足两个要求:1. 使用 Google Play 上下载的微信版本;2. 微信号绑定美国、香港、印度的海外手机号码。

原文链接 https://blog.csdn.net/txw1958/article/details/50527399

 
 
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页