2016-05-03 16:54:45 dream20nn 阅读数 6041
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27819 人正在学习 去看看 秦子恒

1.微信测试号申请:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

2.接口配置填写:由于此处URL只支持线上,而我们开发都在本地,所以要用到下面介绍的


3.Ngrok,一款国外的内网穿透利器,好处是监听本地端口映射到外网,支持外网访问本地环境【微信官方在QQ浏览器中内嵌了微信的本地测试环境其实就是用的Ngrok】这东西被墙了,并且只有注册了【貌似现在要付费?】才支持自定义域名【如果不是自定义域名,那么每次启动域名都随机,第2步中的URL还要每次变,很麻烦】

4.Natapp.cn-->基于Ngrok的免费内网穿透利器,名如其意。官网下载对应系统安装包,WINDOWS下解压,在对应文件夹内打开cmd然后执行下面的命令

【Ngrok -config ngrok.cfg -subdomain myqpp 8080】由于咱们用的Tomcat所以监听8080端口,myapp处输入自己需要设定的名称

5.执行4后下面的域名则为外网地址,访问此域名也就是访问-->127.0.0.1:8080


6.将此域名填写到第2步中的URL中,TOKEN随便填写即可,先不要点击提交【微信开发文档中有个例子,PHP的,用于验证服务器地址的有效性】

7.先不要启动咱的项目,先打开一个没有部署任何APP的Tomcat,在webapp/ROOT下面新建一个JSP页面,页面清空【不需要head,body等信息,清空所有】然后粘贴下面的代码

<%
out.print(request.getParameter("echostr"));
%>

8.点击提交即可绑定成功,然后用自己的微信扫面下方二维码关注测试公众号


9.由于获取用户userinfo,需要设置授权回调域名页面



10.现在可以关掉tomcat然后用咱们自己的项目进行开发了,注意替换对应的appID和appsecret

2016-09-06 16:07:59 chen517611641 阅读数 4422
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27819 人正在学习 去看看 秦子恒

##准备工作
1.ngrok,微信的接口有一些是被动的接收从微信服务器发送的消息的,所以需要提供一个域名给微信服务器,ngrok可以将本机的指定端口,映射到一个域名。花生壳什么的也可以。
2.微信web开发者工具,微信官方的调试工具
##测试账号配置
###测试账号信息
在测试账号管理界面,你可以获取到AppID和APPSecret。
###接口配置信息
这里写图片描述

验证URL有效性成功后即接入生效,成为开发者。如果公众号类型为服务号(订阅号只能使用普通消息接口),可以在公众平台网站中申请认证,认证成功的服务号将获得众多接口权限,以满足开发者需求。

此后用户每次向公众号发送消息、或者产生自定义菜单点击事件时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,然后开发者可以依据自身业务逻辑进行响应,例如回复消息等。

下面的文档描述了这个接口的作用:
http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html
###JS接口安全域名
这里写图片描述
配置在ngrok生成的域名,配置这个配置项的目的是让开发者可以在该域名下调用微信开放的JS接口。
JS-SDK相关的内容可以看这里:
http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
###测试账号二维码
这里写图片描述
用测试账号扫一下这个二维码,就能关注这个测试账号了,回复信息什么的就可以测试了。
###体验接口权限列表
这里写图片描述
测试账号默认大部分接口都是默认开启的,有几个需要手动开启。
这里需要注意的是网页授权获取用户基本信息这个。
这里写图片描述
如上所示,这里需要配置一个域名,网页授权成功回调的时候,必须是这个域名下的地址才行,不然就报scope参数错误或没有scope权限的错误。
至此,开发环境就搭建好了,可以按照微信公众平台开发文档里的微信网页开发部分写一个网页授权获取基本信息的demo了。

2018-07-23 17:46:01 weixin_38306434 阅读数 179
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27819 人正在学习 去看看 秦子恒

微信公众号测试生产环境分离实践

 

背景

最近开发微信公众号,部分功能上线后,为了保证不影响线上正常使用,新功能的开发测试遇到以及需要解决的问题如下:

  1. 调用微信公众号高级接口(授权,支付等)需要配置域名访问,本地测试繁琐,且不能覆盖线上已部署的链接,对已有服务造成影响

  2. 公众号前端业务逻辑涉及到缓存cookie,需要保证测试与生产环境的cookie不冲突

  3. 给需求方演示测试demo,最好要保证与即将上线的子菜单等交互一致,提高交流效率

  4. 测试数据(包括数据库,redis缓存,日志等)与线上数据进行分离

  5. 测试环境与线上部署分离,保证互不影响,提高线上的高可用

  6. 测试环境与生产环境实现自动化部署,提高开发测试效率

解决方案

申请测试公众号以及测试域名

为了满足给需求方演示测试demo,保证与即将上线的交互体验一致,想到最简单的方案就是重新申请公众号供测试使用(幸好以学校研究院的名义,,要不个人申请就没戏了,,,);并且为了保证前端cookie在两个公众号下不冲突,所以测试的时候使用了与生产环境不一样的二级域名,进行cookie隔离

后端的配置分离

目前由于只有一台云服务器,对于后台工程的配置分离,包括:测试与生产工程的端口号,数据库,redis库,微信开发者ID与秘钥,日志。

项目使用了springboot,配置文件目录如下截图:

将工程分为本地(dev),测试(online-test),生产(online)三种环境,并配合application.properties基础配置文件使用,将与环境相关的变量写入相应的properties中即可进行分离,如下列举application-online-test.properties中的配置内容:

注:数据库的分离即是新建不同的库进行区分访问,redis即通过库号区分访问,日志则通过日志名称来区分

后端的部署分离

后端部署脚本执行的流程为:

  1. 使用maven生成jar(本项目为springboot内嵌tomcat,直接执行生成的jar即可提供后台服务)

  2. 在云服务器上执行kill脚本,杀掉并删除待替换的jar进程

  3. 将新jar包传到云服务器上,执行相应jar的启动脚本(启动脚本包括执行jar在后台运行,指明相应的application-??.properties的文件)

因为只有一台云服务器,需要区分测试与生产环境的jar,使用的方案是两种环境生成不同名字的jar,这样也便于kill脚本与启动脚本通过名称来区分jar,进行部署的分离执行,相互不影响

使用maven来生成不同的jar名称,需要修改pom.xml

<profiles>
     <profile>
         <id>online-test</id>
         <properties>
             <project.name>"测试环境的jar名称"</project.name>
         </properties>
     </profile>
     <profile>
         <id>online</id>
         <properties>
             <project.name>"生产环境的jar名称"</project.name>
         </properties>
     </profile>
 </profiles>
 
 <build>
     <finalName>${project.name}</finalName> // project.name即为profile中的properties的标签名
.....其他配置信息
 </build>

最后执行命令 mvn clean package -Ponline-test -Dmaven.test.skip=true,-P后面为profile的id名称,即可生成不同名称的jar

最后执行云服务器的启动脚本,即可启动新的jar服务

nohup java -jar  'jar包的文件位置' --spring.profiles.active='配置文件的后缀(online或online-test)'> /dev/null 2>&1 &

前端的配置分离

前端的配置变量包括:请求测试与生产端口号不同,域名不同(涉及授权等重定向链接的不同),微信公众号的ID不同。

代码上将这些变量写到全局一处调用,通过开关注释进行分离控制

前端的部署分离

因为使用单台云服务器,测试与生产环境的前端工程都需要使用到80端口,因为微信高级接口有些仅允许80端口程序调用,所以对于ngnix的配置,使用了配置虚机主机的方案。

具体步骤如下:

  1. 确保容器/etc/nginx/nginx.conf文件中有:include /etc/nginx/conf.d/*.conf;

  2. 在容器目录/etc/nginx/conf.d/下面新建文件site1.conf,site2.conf,文件名任意,后缀名需要与步骤1配置的一致,这里为.conf。site1代表我们的生产环境工程,site2代表我们的测试环境工程,该文件编写如下:

server {
    listen 80;
    server_name //代表该虚拟主机的二级域名
    root //前端工程代码在服务器中的位置;
    index index.html index.htm;
    ...其他配置略
}

前端工程的部署脚本流程是将代码替换到相应配置的目录下,平滑重载ngnix即可

systemctl reload nginx.service  //reload重载文件,客户端无异常

方案总结

通过申请新的测试公众号,部署不同的域名配置到子菜单上,可以达到与线上公众号相同的交互,前端通过访问后端不同接口的服务,将数据库,redis缓存,日志信息通过后台配置实现了生产与测试的完全分离,可以说如上的解决方案,满足了开始列举的所有需求点,最终将前后端的部署实现脚本自动化,也节省了部署时间,提高开发测试的效率。

2018-01-10 10:26:10 joefany 阅读数 100785
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27819 人正在学习 去看看 秦子恒

官方链接:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

扫描关注后登录

需要填写接口配置,一个公网能访问的域名,推荐用natapp。

填写JS接口安全域名 ,设置JS接口安全域后,通过关注该测试号,开发者即可在该域名下调用微信开放的JS接口,请阅读微信JSSDK开发文档

注意:不知道啥原因,用自己的帐号申请测试帐号后貌似不能立即关注,但是同事的微信能关注。自己的帐号是过了两天就能关注了。



2017-08-04 21:25:08 u012432468 阅读数 243
  • 微信支付开发-微信公众号开发12-微信开发php

    微信公众平台开发之微信支付开发是子恒老师《微信公众平台开发》视频教程的第12部。详细讲解了用php进行微信支付的开发。内容包含获取支付密钥,微信公众号支付开发,扫码支付,微信刷卡支付,异步处理支付结果等等。欢迎反馈,微信/QQ:68183131

    27819 人正在学习 去看看 秦子恒

第一步 注册一个公众号

1.1百度输入“微信公众平台”就能够进入公众号平台完成注册或登录。

1.2可以先熟悉一下微信本身的可编辑模式下消息的发送与回复之类的。。

1.3进入开发者模式,在左侧菜单栏找到“开发”菜单,里面会有比较详细的有关开发的知识等。

1.4由于个人注册只能注册订阅号,未经认证的公众号是不能直接进入开发者模式的,不过没关系,微信给每个订阅号提供了一个公众平台测试账号,在“开发者工具”--->“公众平台测试账号”(后面会用到)

如下图:


第二步:环境准备

2.1由于本地服务器不能实现和外网的通信,所以,我们需要一个外网映射内网的工具。

我用的是ngrok(很好下载),这是一个国外的服务器,所以速度可能有点慢,但是免费。他也有部署在国内的服务器,可以自定义域名(以前免费,现在收费)。

2.2配置ngrok。在命令行进入ngrok安装目录,输入ngrok即可进入ngrok

2.2 配置映射地址,输入ngrok 8081 ngrok http 8081由于版本不一样所以输入命令有差别。因为我的本地服务器Tomcat的端口设置为8081所以是ngrok http 8081,如果你是8080自行改动。

 

 

红线位置即是随机分配给你的映射地址,也就是说,当你启动本地服务器访问localhost:8081时和访问http://19b82289.ngrok.io是一样的效果。

 

第三步,创建Java项目(最好用maven项目,开发环境idea)部署本地服务器,保证部署无误,即能正确访问localhost:8081;(具体方法,不多说了,可百度idea如何创建maven项目)(虽然我在这一步浪费了好长时间,因为一个无知的错误)

可以给大家说一下maven的依赖方法

当你需要引入某个jar包时,需要在pom.xml中加入依赖。

首先你需要在https://mvnrepository.com/这个网站里搜索是否有你要用到的包,比如说搜dom4j


 

点进去一个,


 

点击verSion下的任意一个


红框内的代码即是你要加入pom.xml的代码。更新maven即可。

第四步,基本代码构成(本测试使用J2ee+tomact

4.1创建目录如下


 

4.2cn.yang.util主要是一些工具类

  Dao里是对象类

 Serlet里是servlet

CheckUtil代码:

//开发者提交信息后,微信服务器将发送get请求到填写的服务器地址URL上,get请求携带四个参数,

 

package cn.yang.util;
/**
 * Created by jibei on 2017/7/20.
 * 验证服务器地址的有效性
 */
        
import java.io.UnsupportedEncodingException;
        import java.security.MessageDigest;
        import java.security.NoSuchAlgorithmException;
        import java.util.Arrays;
public class CheckUtil {
    private static final String token="imooc";//自定义的

    public static boolean checkSignature(String signature,String timestamp,String nonce){
        String[] arr=new String[]{token,timestamp,nonce};
        //排序
        
Arrays.sort(arr);
        //生成字符串
        
StringBuffer content=new StringBuffer();
        for(int i=0;i<arr.length;i++){
            content.append(arr[i]);
        }
        //sha1加密
        
String temp=getSha1(content.toString());

//对比
        return temp.equals(signature);
    }
    public static String getSha1(String str){
        if (null == str || 0 == str.length()){
            return null;
        }
        char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] buf = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

 

MessageUtil类是xml转换为集合以及文本转化为xml的方法(因为微信是xml格式的)

 

package cn.yang.util;

/**
 * Created by jibei on 2017/7/29.
 */
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

import com.thoughtworks.xstream.XStream;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.imooc.dao.TextMessage;
public class MessageUtil {
    public static Map<String,String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
        //将XML转换成集合
        
Map<String,String> map=new HashMap<String,String>();
        SAXReader reader=new SAXReader();
        //从reuest中获取输入流
        
InputStream ins=request.getInputStream();
        Document doc=reader.read(ins);
        Element  root=doc.getRootElement();
        List<Element> list=root.elements();
        for(Element e:list){
            map.put(e.getName(),e.getText());
        }
        //关闭输入流
        
ins.close();
        return map;
    }

    public static String  textMessageToXml(TextMessage textMessage){
        //将文本转换成XML
        
XStream xstream=new XStream();
        //将xml的根节点替换成xml即<xml>jkkkkk</xml>
        
xstream.alias("xml",textMessage.getClass());
        xstream.toXML(textMessage);
        return  xstream.toXML(textMessage);
    }
}

TextMessage是文本对象,包括他的基本属性和方法

package com.imooc.dao;

/**
 * Created by jibei on 2017/7/29.
 */
public class TextMessage {
    private String ToUserName;
    private String FromUserName;
    private String CreateTime;
    private String MsgType;
    private String Content;
    private String MsgId;


    public String getToUserName() {
        return ToUserName;
    }

    public void setToUserName(String toUserName) {
        ToUserName = toUserName;
    }

    public String getFromUserName() {
        return FromUserName;
    }

    public void setFromUserName(String fromUserName) {
        FromUserName = fromUserName;
    }

    public String getCreateTime() {
        return CreateTime;
    }

    public void setCreateTime(String createTime) {
        CreateTime = createTime;
    }

    public String getMsgType() {
        return MsgType;
    }

    public void setMsgType(String msgType) {
        MsgType = msgType;
    }

    public String getContent() {
        return Content;
    }

    public void setContent(String content) {
        Content = content;
    }

    public String getMsgId() {
        return MsgId;
    }

    public void setMsgId(String msgId) {
        MsgId = msgId;
    }




}

WeiX

package com.imooc.servlet;
import cn.yang.util.CheckUtil;
import cn.yang.util.MessageUtil;
import com.imooc.dao.TextMessage;
import org.dom4j.DocumentException;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class WeiX extends HttpServlet{
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException{
        String signature=req.getParameter("signature");
        String timestamp=req.getParameter("timestamp");
        String nonce=req.getParameter("nonce");
        String echostr=req.getParameter("echostr");
        PrintWriter out=resp.getWriter();
        if(CheckUtil.checkSignature(signature,timestamp,nonce)){
            out.print(echostr);
        }
    }

    protected void doPost(HttpServletRequest req,HttpServletResponse resp)
            throws ServletException,IOException{
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter out=resp.getWriter();
        try {
            Map<String,String> map= MessageUtil.xmlToMap(req);
            String fromUserName=map.get("FromUserName");
            String toUserName=map.get("ToUserName");
            String msgType=map.get("MsgType");
            String content=map.get("Content");
            String message=null;
            //判断这个消息是否为文本消息
            
if("text".equals(msgType)){
                TextMessage text=new TextMessage();
                text.setFromUserName(toUserName);
                text.setToUserName(fromUserName);
                text.setMsgType("text");
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                
text.setCreateTime(df.format(new Date()) );
                text.setContent("您发送的消息是"+content);
                message=MessageUtil.textMessageToXml(text);
            }
            out.print(message);
            System.out.println(message);
        } catch (DocumentException e) {
            e.printStackTrace();
        }finally {
            out.close();
            //关闭
        
}

    }
}

 

 

第五步:接口配置

由第一步1.4进入测试号,接口配置信息里,填写(我已经填过了)

 

 

配置时要保证你的tomcat是启动的,也就是说你的代码是无编译错误的否则tomcat启动不起来。

如果出现配置失败也就是说微信端无法找到你所给的地址。

 

第六步 测试

打开你的微信,扫一扫你的测试公众号二维码关注,发送消息,看能否收到回复。

Ok!如此算是入了微信开发的一个小门。

 

 

 

 



没有更多推荐了,返回首页