2019-09-28 17:36:40 weixin_38742453 阅读数 4344
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

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

沙箱环境

又称沙盘,为了开发与调试所提供的环境,它与生产环
境互相隔离,但具有生产环境几乎完全相同的功能
蚂蚁金服开放平台——开发者中心
1.https://openhome.alipay.com
2.提供的调试产品
3. APP支付
4.当面付
5.电脑网站支付

接入步骤
1 创建应用并获取APPID
2. 配置密钥
3. 搭建和配置开发环境
4. 使用SDK
5.线上验收

为了更好的说明上述问题,这里分享一段Leon老师的课程视频

spring cloud

第一步:创建应用并获取APPID

 准备工作
 支付宝账号
 必须在开放平台完成实名认证才能使用开放平台服务
 生成应用唯一标识(APPID)  创建登记应用
 提交実核
 开发阶段可使用默认的沙箱应用
 开发者中心-研发服务-沙箱应用
 每个应用对应一个APPID
5/12

第二步:配置密钥

 生成RSA密钥对
 应用私钥
 应用公钥
 上传应用公钥
 平台自动生成支付宝公钥

第三步:搭建和配置开发环境

 下载SDK
 https://docs.open.alipay.com/54/103419
 接口调用属性配置

在这里插入图片描述

第四步:SDK的使用2-1  SDK包说明

 alipay-sdk-java*.jar:支付宝SDK编译文件jar
 alipay-sdk-java*-source.jar:支付宝SDK源码文件jar
 commons-logging-1.1.1.jar:SDK依赖的日志jar
 commons-logging-1.1.1-sources.jar:SDK依赖的日
志源码jar
 核心API
 AlipayClient:封装签名与验证
 AlipayTradePagePayRequest:支付请求类
 AlipayTradePagePayModel:封装请求支付信息 8/12
第四步:SDK的使用2-2  服务器异步通知
 notify_url
 支付宝使用POST方式,保证99.9999%的通知到达率
 页面跳转同步通知
 return_url
 支付宝使用GET方式,是由宠户浏览器触发的一个通知,
不保证其到达率

第五步:线上验收

 在沙箱环境完成功能调试后,必须将支付宝网关、
appid、应用私钥、支付宝公钥修改成正式环境的配
置,并在蚂蚁正式环境进行完整的功能验收测试
 完善应用基本信息
 应用名称
 图标
 签约支付产品
 开发配置
 等待実核

总结

 接入第三方(支付宝)支付
 创建应用并获取APPID
 配置密钥
 搭建和配置开发环境
 SDK的使用
 线上验收

最后,给大家分享一下leon老师的课程《7周Spring Cloud微服务架构项目实战》我最近学习过,感觉很不错,所以分享给大家

博文中展示的视频也是节选至Leon老师的精品课程《7周Spring Cloud微服务架构项目实战》

Leon老师主攻Java、Android,7年项目开发和教学经验,4年金融上市公司技术Leader,擅长大型软件架构、微服务应用架构设计。笔者对于Leon老师是很崇拜的。

《7周Spring Cloud微服务架构项目实战》课程主要围绕电商项目大觅网的业务场景,基于微服务原则设计电商项目。
学了这个课程会学到:
1.多种诸如Eureka、Feign、Hystrix、Ribbon、Zuul、Config等技术使用方法,另外
2.基于虚拟化技术Docker+Jenkins实现程序自动发布
3.基于Mycat实现第三方支付接入、整个项目的高并发测试等
**

下面附全部课程的视频链接,希望对您有用:
https://edu.csdn.net/course/detail/9995?utm_source=springcloud_7

扫码加小姐姐微信拉入交流群,可免费听技术讲座+领学习资料+视频课免费看
在这里插入图片描述

2018-02-09 12:12:50 qq962464qq 阅读数 1089
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

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

微信公众号开发的时候大多数人都是看官方文档,但是这样很耗费时间,下面是一个Demo的讲解,可以让初次开发者快速的搭建好开发环境。

首先在公众号开发之前我们要做一个重要准备,那就是把我们本地的项目部署起来并将端口映射到外网,让外网也可以访问我们的项目,请看我之前转载的一片文章。

开发准备工作:点击打开链接http://blog.csdn.net/qq962464qq/article/details/79296319

Demo:Demo下载,Demo中采用简单的Spring MVC+mybaitis进行开发,Demo结构如下

我们用到的文件讲解

controller:接收请求

dao:和mapper中的sql对应,用于操作数据库

entity:实体

mapper:mybaitis的操作数据库的.xml文件,编写的sql

util:工具类

weixin:微信开发用到的一些代码(下面会详细讲解)

配置文件:applicationContext.xml和Spring-MVC.xml是spring的一些配置language.....文件是用来做页面中英文切换的(可以不要)system.properties文件配置了全局的一些变量,如Token等

这个准备工作的作用:

在公众号开发之前我们需要在微信官网平台的公众号(测试号也可以)填写一个urlToken,token可以自己命名,但是必须和你的项目中的Token一致,在你点击确 定的时候微信将访问你的url,加密你填写的token和你本地设置的token(本地需要加密,加密代码后面讲解)进行对比,对比成功则完成设置。

Demo讲解

1.绑定URL和Token

URL是微信平台访问的链接,用来校验Token的请求地址(DoMessageController中)


2.接收请求

接收关注,消息等请求,绑定了图灵机器人,实现智能问答。关注时进行消息推送(DoMessageController中)

/**
     * 处理微信发来的请求
     * @param request
     * @return xml
     */
    public String processRequest(HttpServletRequest request) {
        // xml格式的消息数据
        String respXml = null;
        // 默认返回的文本消息内容
        String respContent = "未知的消息类型!";
        try {
            // 调用parseXml方法解析请求消息
            Map<String, String> requestMap = MessageUtil.parseXml(request);
            // 发送方帐号
            String fromUserName = requestMap.get("FromUserName");
            // 开发者微信号
            String toUserName = requestMap.get("ToUserName");
            // 消息类型
            String msgType = requestMap.get("MsgType");
            // 回复文本消息
            TextMessage textMessage = new TextMessage();
            textMessage.setToUserName(fromUserName);
            textMessage.setFromUserName(toUserName);
            textMessage.setCreateTime(new Date().getTime());
            textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
            // 文本消息
            if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
            	//消息内容
            	String content = requestMap.get("Content");
            	Robot robot = new Robot();
            	//调用机器人对话
                respContent = robot.dialogue(content, fromUserName);
            }
            // 图片消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
                respContent = "您发送的图片我没见过!";
            }
            // 语音消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
                respContent = "我听不见您说的什么,还是打字吧!";
            }
            // 视频消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
                respContent = "您发送视频我没看过!";
            }
            // 视频消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) {
                respContent = "您发送的是小视频消息!";
            }
            // 地理位置消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
                respContent = "这个地方我没去过!";
            }
            // 链接消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
                respContent = "您发送的是链接消息!但是我不认识!";
            }
            // 事件推送
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件类型
                String eventType = requestMap.get("Event");
                // 关注
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                    respContent = "欢迎关注上海质子重离子医院设备设施综合运行管理微信平台!";
                    //拉取用户数据
                    String url = "https://api.weixin.qq.com/cgi-bin/user/info";
                    String param = "access_token="+accessTokenService.getAccessToken().getAccesstoken()+"&openid="+fromUserName+"&lang=zh_CN";
                    JSONObject followPersonJson =  HttpUtil.sendGetOfJson(url, param);
                    followPersonJson.remove("tagid_list");
                    FollowPerson followPerson = (FollowPerson)JSONObject.toBean(followPersonJson,FollowPerson.class);
                    if(followPersonService.listFollowPerson(followPerson).size()==0){
                    	followPersonService.saveFollowPerson(followPerson);
                    	//tempMsgPushService.pushAllUser();
                    }
                }
                // 取消关注
                else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                    //取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
                	FollowPerson followPerson = new FollowPerson();
                	followPerson.setOpenid(fromUserName);
                	followPersonService.delFollowPerson(followPerson);
                }
                // 扫描带参数二维码
                else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
                    // 处理扫描带参数二维码事件
                }
                // 上报地理位置
                else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
                    //处理上报地理位置事件
                }
                // 自定义菜单
                else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
                    //处理菜单点击事件
                }
            }
            // 设置文本消息的内容
            textMessage.setContent(respContent);
            // 将文本消息对象转换成xml
            respXml = MessageUtil.messageToXml(textMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return respXml;
    }
3.自定义菜单

weixin/InitMenu.java


   

//使用线程初始化access_Token
    public void init() throws ServletException {  
		try {
			ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
			AccessTokenService accessTokenService = (AccessTokenService) applicationContext.getBean("accessTokenService");
			//获取access_token
			String aturl = "https://api.weixin.qq.com/cgi-bin/token";
			//参数配置在system.properties中
			String param = "grant_type=client_credential&appid="+Common.getSystemProperty("appID")+"&secret="+Common.getSystemProperty("appsecret");
			JSONObject jsonObj = HttpUtil.sendGetOfJson(aturl, param);
			String access_token = jsonObj.getString("access_token");
			int expires_in= jsonObj.getInt("expires_in");
			AccessToken accessToken = new AccessToken();
			if(StringUtils.isNotBlank(access_token) && expires_in>0){
				accessToken.setAccesstoken(access_token);
				accessToken.setExpires(expires_in);
				//保存access_Token到数据库
				accessTokenService.delAccessToken();
				accessTokenService.saveAccessToken(accessToken);;
			}
			if(Common.isnull(accessToken)){
				System.out.println("access_Token错误");
			}
			String url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="+accessToken.getAccesstoken();
			//json参数
			JSONObject jsonParam = new JSONObject();
			JSONArray jsonArr1 = new JSONArray();
			JSONArray jsonArr2 = new JSONArray();
			//一级菜单项
			JSONObject jsonParam1 = new JSONObject();
			//二级菜单项
			JSONObject jsonParam2 = new JSONObject();
			//第一组
			jsonParam1.put("name", "首页");
			//添加二级
			jsonParam2.put("type", "view");
			jsonParam2.put("appid", Common.getSystemProperty("appID"));
			jsonParam2.put("name", "登陆");
			jsonParam2.put("url", "http://e23c7752.ngrok.io");
			
			jsonArr2.add(jsonParam2);
			jsonParam2.clear();
			//继续添加二级
			//将二级添加到1级下
			jsonParam1.put("sub_button", jsonArr2);
			
			jsonArr1.add(jsonParam1);
			
			jsonParam2.clear();
			jsonParam1.clear();
			/*//第二组
			jsonParam1.put("name", "首页");
			jsonParam1.put("type", "view");
			jsonParam1.put("url", "www.baidu.com");
			
			jsonParam.put("button", jsonParam1);
			
			jsonParam2.clear();
			jsonParam1.clear();
			//第二组
			jsonParam1.put("name", "首页");
			jsonParam1.put("type", "view");
			jsonParam1.put("url", "www.baidu.com");
			
			jsonParam.put("button", jsonParam1);
			
			jsonParam2.clear();
			jsonParam1.clear();*/
			
			jsonParam.put("button", jsonArr1);
			System.out.println(jsonParam);
			//初始化返回
			//JSONObject rsJson = HttpUtil.sendPost(url, jsonParam);
			JSONObject rsJson = HttpUtil.sendPostOfJson(url, jsonParam);
			String  errmsg= rsJson.getString("errmsg");
			int errcode= rsJson.getInt("errcode");
			if(errcode==0 && errmsg.equals("ok")){
				System.out.println(DateTimeUtil.formatDate(new Date(), DateTimeUtil.yyyy_MM_dd_HH_mm_ss)+"  success:初始化菜单成功");
			}else{
				System.out.println(DateTimeUtil.formatDate(new Date(), DateTimeUtil.yyyy_MM_dd_HH_mm_ss)+":    error:初始化菜单失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }  
其余核心代码中都有注释

2016-11-15 11:38:46 qq_24091555 阅读数 20060
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

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

           由于项目需要,需要接触微信开发,并要调用微信的JS-SDK里面的接口。

       因为经验缺乏,我百度一下关于微信开发的资料,但收集的资料都不尽人意。网上的主流的微信开发是采用PHP开发的,而本人学的Java。所以对PHP微信开发只能看懂思路。更有的是,网上一些微信开发视频,也是和PHP有关的,关于用Java开发的甚少。

       无奈之下,我只好苦啃微信开发文档。大家都知道,微信官方给的开发文档真的有点那个啥,一个功能实现非要分几个地方来说,看完这块,又得点击另一个页面看完另一块,甚是麻烦。这样的设定也让我走了好多坑。

但功夫不负有心,在研究透了微信开发文档之后,我顺利在在项目中完成微信开发。现在我将微信开发的经验分享一下,希望对大家有所帮助。

       微信JS-SDK是微信公众号平台面向网页开发这提供基于微信内的网页开发工具包。接口大类分为:基础接口、分享接口、图像接口、音频接口、智能接口、设备信息、地址位置、摇一摇周边、界面操作、微信扫一扫、微信小店、微信卡劵和微信支付。一般使用频率高的就是分享接口、地理微信、微信扫一扫和微信支付。

接下来,我将主要讲解如何调用微信分享接口。

第一步,准备内网映射工具,ngrok。不清楚这个的同学可以去百度一下。https://ngrok.com为ngrok官网。要进行微信开发,内网映射工具是不可少。毕竟,我们程序员进行开发,要测试开发的产品是否能用,都先在自己的电脑跑一下。但由于ngrok的服务器在外国的,鉴于天朝的墙太高,访问可能不稳定。所以我推荐的是国内的natapp,免费和收费的都有,服务毕竟稳定可靠,只不过要想自定义二级域名就得交费成为VIP咯。

第二步,配置JS接口安全域名。登录要进行开发的公众号,点击公众设置--->功能设置。设置JS接口安全域名,要注意三点:①填写域名前面不需加上http://,例如你的域名是http://test.com,直接填写test.com即可;②域名默认80端口,只支持80和443端口,所以域名后面不能添加端口号。③该域名为你调用微信JS-SDK接口域名。

第三步,引用JS文件。在需要调用JS接口的页面引入http://res.wx.qq.com/open/js/jweixin-1.0.0.js 。


第四步,通过config接口注入权限验证配置 。具体参数有什么用处,在截图都有注释讲解。其中jsApiList为我们要使用的接口,我在下面共引用了五个接口,分别为微信好友分享、QQ好友分享、腾讯微博分享、QQ空间分享和朋友圈分享。调用的都是分享的接口。至于其他接口列表,可以去微信开发文档那浏览一下。这里就不详说。

        第五步,在服务器生成相关参数传到调用JS-SDK页面,完成授权。这是最重要的一步。如上图所示,appId,timestamp,nonceStr,signature都为必填参数。下面我将会详细说说如何生成这些参数并传回页面。

appId为开发的微信公众号的AppID(应用ID),我们可以在登录微信公众号,在开发选项中点击基本配置来查看。

timestamp为系统生成的时间戳。


nonceStr为服务器随机生成的字符串。



signature为微信JS-SDK使用权限算法。在生成signature之前,我们要拿到jsapi_ticket。官方文档是这样解释的:


我们要注意三个地方。jsapi_ticket要缓存两个小时,每过两个小时,向微信那边请求一次。获取jsapi_ticket要通过access_token。那么我们该如何获取access_token呢?


从文档可以看出,access_token需要AppID和AppSercet两个参数。而且access_token和jsapi_ticket一样,有效期皆为两小时。这就要求我们服务器要缓存access_token和jsapi_ticket,当有效期一过,就重新请求。有的人采用是用数据库来存取这两个参数,而我采用的是用Quartz定时器。关于Quartz定时器的使用,可浏览我上篇博客《SSH与Quartz集成》,里面有关于Quartz的使用方法。

AppSercet可在与APPID同一页面获取。接下来,调用接口,获取access_token。



接下来,我们用access_token去获取jsapi_ticket。


获取jsapi_ticket,就可以进行生成签名。在此之前,先看一下官方文档的签名算法。



用代码实现。


第六步,传生成的参数给网页。



第七步,调用已授权的JS接口。


第八步,利用微信Web开发者工具调试,看看是否授权成功。(微信web开发者工具可在微信开发下载)。



2016-12-08 17:14:37 qq_25821067 阅读数 8785
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

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

微信上接入平台的demo是PHP的,没得java的,所以我自己做接入的时候遇到了一点小问题。用java做带薪开发,首先就要先通过微信的接入配置,大概原理就是微信往服务器发送一些数据,然后在服务器端做一些数据的处理,再返回数据就行了。

微信官方的名称是:

验证服务器地址的有效性

下面是微信官方的文档:

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

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

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

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

1:写个servlet类,来处理微信发送过来的数据:
package com.levi.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.levi.utils.SHA1;

/**
 * Servlet implementation class WeiXin
 */
public class WeiXin extends HttpServlet {
	private static final long serialVersionUID = 1L;
	 private static String Token = "leviweixin";  //这个是之前在微信上填写的Token数据,可以自定义
    /**
     * @see HttpServlet#HttpServlet()
     */
    public WeiXin() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		 System.out.println("get请求,正确");
		System.out.println("获得微信请求!");
		String signature=request.getParameter("signature");
		String timestamp=request.getParameter("timestamp");
		String nonce=request.getParameter("nonce");
		String echostr=request.getParameter("echostr");
		System.out.println("signature="+signature);
		System.out.println("timestamp="+timestamp);
		System.out.println("nonce="+nonce);
		System.out.println("echostr="+echostr);
		System.out.println("Token="+Token);
		
		 List<String> params = new ArrayList<String>();  
         params.add(Token);  
         params.add(timestamp);  
         params.add(nonce);  
         //1. 将token、timestamp、nonce三个参数进行字典序排序  
         Collections.sort(params, new Comparator<String>() {  
             @Override  
             public int compare(String o1, String o2) {  
                 return o1.compareTo(o2);  
             }  
         }); 
         //2. 将三个参数字符串拼接成一个字符串进行sha1加密  
         String temp = SHA1.encode(params.get(0) + params.get(1) + params.get(2));  
         if (temp.equals(signature)) {  
        	 System.out.println("原:"+signature);
        	 System.out.println("测试:"+temp);
        	 System.out.println("匹配正确,传回微信了");
             response.getWriter().write(echostr);  
             System.out.println("传回微信成功");
         }  
		 else {  
        System.out.println("没有传回去数据,");
     } 
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	 System.out.println("post请求,错误了");
	}

}

2:需要一个SHA1 的util类:
/*
 * 微信公众平台(JAVA) SDK
 *
 * Copyright (c) 2016, Ansitech Network Technology Co.,Ltd All rights reserved.
 * http://www.ansitech.com/weixin/sdk/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.levi.utils;

import java.security.MessageDigest;

/**
 * <p>Title: SHA1算法</p>
 *
 * @author qsyang<yangqisheng274@163.com>
 */
public final class SHA1 {

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
                           '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * Takes the raw bytes from the digest and formats them correct.
     *
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
3、配置下web.xml就行了
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>wx</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <description></description>
    <display-name>WeiXin</display-name>
    <servlet-name>WeiXin</servlet-name>
    <servlet-class>com.levi.service.WeiXin</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>WeiXin</servlet-name>
    <url-pattern>/WeiXin</url-pattern>
  </servlet-mapping>
</web-app>



点击提交,如果正确会显示配置成功。

注意事项:
1、一定要用到外网IP映射,可以用花生壳,或者用ngrok。端口要用80端口。用外网映射的目的就是模拟服务器,然后微信才能够给服务器发信息并且验证;
2、要多连续点击几次提交,直到ok为止,我测试的时候就发现,明明是对的,但是微信就说配置失败,后面我多次连续点击提交,非常快的速度连续点击提交。有个前提,要代码没写错哈,其实你把上面的3个代码块的文件复制进去应该是没得问题的。

2017-09-19 20:10:00 weixin_33935777 阅读数 33
  • 微信h5支付开发-php开发微信h5支付demo

    会员免费看,http://edu.csdn.net/lecturer/842右侧可办理会员卡。微信h5支付开发是子恒老师《子恒说微信开发》视频教程的第17部。详细讲解了微信H5支付开发,内容包含开通H5支付,实现微信h5支付,订单查询,关闭订单等等。欢迎反馈,微信号:QQ68183131

    7977 人正在学习 去看看 秦子恒
服务项目 新手技术咨询 企业技术咨询 定制开发
服务说明 QQ有问必答 QQ、微信、电话 微信开发、php开发,网站开发,系统定制,小程序开发
价格说明 200元/月 1000/月 商议
      联系 851 488 243,点击这里给我发消息 备注:模板消息

一、首先先确定H5支付权限已经申请!(需要微信h5支付demo的可以加 851 488 243 点击这里给我发消息 备注:h5支付,可能是有偿~)

二、开发流程

1、用户在商户侧完成下单,使用微信支付进行支付

2、由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB

3、统一下单接口返回支付相关参数给商户后台,如支付跳转url(参数名“mweb_url”),商户通过mweb_url调起微信支付中间页

4、中间页进行H5权限的校验,安全性检查(此处常见错误请见下文)

5、如支付成功,商户后台会接收到微信侧的异步通知

6、用户在微信支付收银台完成支付或取消支付,返回商户页面(默认为返回支付发起页面)

7、商户在展示页面,引导用户主动发起支付结果的查询

8,9、商户后台判断是否接到收微信侧的支付结果通知,如没有,后台调用我们的订单查询接口确认订单状态

10、展示最终的订单支付结果给用户

三、开发过程

1、配置相关参数

class WechatPayConf
{
	
	const APPID = '';//APPID
	const MCH_ID = '';//商户号
	const KEY = '';//商户key
	const NOTIFY_URL = '';//回调地址

}

 

2、统一下单

接口链接

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

请求参数

<xml>
<appid>wx2421b1c4370ec43b</appid>
<attach>支付测试</attach>
<body>H5支付测试</body>
<mch_id>10000100</mch_id>
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
<notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url>
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
<out_trade_no>1415659990</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>MWEB</trade_type>
<scene_info>{"h5_info": {"type":"IOS","app_name": "王者荣耀","package_name": "com.tencent.tmgp.sgame"}}</scene_info>
<sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>

  

PHP代码

/**
 * 统一支付接口类
 */
class UnifiedOrder_pub extends Wxpay_client_pub
{	
	function __construct() 
	{
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		//设置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["notify_url"] == null) {
				throw new SDKRuntimeException("缺少统一支付接口必填参数notify_url!"."<br>");
			}elseif ($this->parameters["trade_type"] == null) {
				throw new SDKRuntimeException("缺少统一支付接口必填参数trade_type!"."<br>");
			}elseif ($this->parameters["trade_type"] == "JSAPI" &&
				$this->parameters["openid"] == NULL){
				throw new SDKRuntimeException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!"."<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);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	
	/**
	 * 获取prepay_id
	 */
	function getPrepayId()
	{
		$this->postXml();
		$this->result = $this->xmlToArray($this->response);
		$prepay_id = $this->result["prepay_id"];
		return $prepay_id;
		
	}
	
}

 

如果调用正常,就会得到一个支付url

 

其它常见错误

 

序号问题错误描述解决方法
1 268498465 网络环境未能通过安全验证,请稍后再试 1. 商户侧统一下单传的终端IP(spbill_create_ip)与用户实际调起支付时微信侧检测到的终端IP不一致导致的,这个问题一般是商户在统一下单时没有传递正确的终端IP到spbill_create_ip导致,详细可参见客户端ip获取指引

2. 统一下单与调起支付时的网络有变动,如统一下单时是WIFI网络,下单成功后切换成4G网络再调起支付,这样可能会引发我们的正常拦截,请保持网络环境一致的情况下重新发起支付流程

2 268443815 商家参数格式有误,请联系商家解决

1. 当前调起H5支付的referer为空导致,一般是因为直接访问页面调起H5支付,请按正常流程进行页面跳转后发起支付,或自行抓包确认referer值是否为空


2. 如果是APP里调起H5支付,需要在webview中手动设置referer,如(
Map<string,string> extraHeaders = new HashMap<string,string>();
extraHeaders.put("Referer", "商户申请H5时提交的授权域名");//例如 http://www.baidu.com ))

3 268443816 商家存在未配置的参数,请联系商家解决 1,当前调起H5支付的域名(微信侧从referer中获取)与申请H5支付时提交的授权域名不一致,如需添加或修改授权域名,请登陆商户号对应的商户平台--"产品中心"--"开发配置"自行配置 

2,如果设置了回跳地址redirect_url,请确认设置的回跳地址的域名与申请H5支付时提交的授权域名是否一致
4 268498468 支付请求已失效,请重新发起支付 统一下单返回的MWEB_URL生成后,有效期为5分钟,如超时请重新生成MWEB_URL后再发起支付
6 请在微信外打开订单,进行支付 H5支付不能直接在微信客户端内调起,请在外部浏览器调起

转载于:https://www.cnblogs.com/memor-y/p/7553837.html

PHP实现微信支付的demo

博文 来自: s371795639

php开发微信demo

阅读数 3441

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