微信H5支付功能开发
本文介绍的是微信H5支付功能开发,也就是在微信之外的H5页面支付。
首先我们需要先看微信的官方文档https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1,这里面几乎介绍了全部流程了。等你了解大概流程之后,需要在微信公众平台和微信商户平台拿到或者配置一下参数。
appid:公众平台的appid
商户号:公众平台的商户号
商户密钥:key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
最后在商户平台后台产品中心-->开发配置 中添加H5支付回调域名,域名必须是通过备案的。(下图借用了某个兄弟的图,我懒得上后台截图了)
花了不少时间去填这些坑,填完了我们就可以吭哧吭哧开工搬砖了!
写完支付别忘了还有订单查询功能需要开发,主要为了查询出哪些王八蛋就只是来看看不买东西还占库存。不给钱的我们需要把库存要回来。
/**
* 保存订单并发起支付请求
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "/save")
public void save(HttpServletRequest request, HttpServletResponse response) throws IOException{
//判断用户是否登录
String mobileNumber = (String)request.getSession().getAttribute("mobileNumber");
if(StringUtils.isEmpty(mobileNumber)){
return;
}
response.setContentType("text/xml;charset=utf-8");
PrintWriter out = response.getWriter();
ResponMsg msg = new ResponMsg();
msg.setSuccess(true);
String content = "提交成功";
try{
//获取用户选择的票务信息,邮寄信息
String ticketId = request.getParameter("ticketId");
String ticketCount = request.getParameter("ticketCount");
String userName = request.getParameter("userName");
String userAddress = request.getParameter("userAddress");
String userMobile = request.getParameter("userMobile");
//参数验证
if(StringUtils.isEmpty(ticketId) || StringUtils.isEmpty(ticketCount) || StringUtils.isEmpty(userAddress)
|| StringUtils.isEmpty(userMobile) || StringUtils.isEmpty(userName)){
content = "请正确且完整填写收货信息!";
msg.setCode(-2);
return;
}
//判断是否有可售票 有则创建订单预留票并发起支付
ActTicket actTicket = showService.queryTicketById(Integer.valueOf(ticketId));
if(actTicket.getTicketStock() - Integer.valueOf(ticketCount) < 0){
content = "抱歉,已售完!感谢关注!";
msg.setCode(-1);
return;
}
//创建订单
// 自己网站上的订单号
int randomNum = (int) (Math.random() * 1999+5000);
//String out_trade_no = TimeUtils.getSysTime("yyyyMMddHHmmss") + randomNum;
String orderNO = TimeUtils.getSysTime("yyyyMMddHHmmss") + randomNum;
ActUserAddress actUserAddress = new ActUserAddress(mobileNumber, userName, userMobile,userAddress, orderNO);
ActOrder actOrder = new ActOrder();
actOrder.setOrderNumber(orderNO);
actOrder.setTicketId(actTicket.getId());
actOrder.setProductName(actTicket.getTicketLevel());
actOrder.setProductPrice(actTicket.getTicketPrice());
actOrder.setProductCount(Integer.valueOf(ticketCount));
actOrder.setTotalPay(actTicket.getTicketPrice() * Integer.valueOf(ticketCount));
actOrder.setPayType(1);
actOrder.setStatement(1);
actOrder.setUserAccount(mobileNumber);
actOrder.setActUserAddress(actUserAddress);
System.out.println(mobileNumber + " 创建订单:" + actOrder.toString());
//缓存数据
request.getSession(true).setAttribute("actOrder", actOrder);
showService.createOrder(actOrder);
//发起支付
content = "/show/wxPayH5";
msg.setCode(9);
}catch(Exception e){
msg.setCode(0);
msg.setSuccess(false);
msg.setMessage("当前人数过多,请稍后再来。");
e.printStackTrace();
}finally{
msg.setMessage(content);
out.print(JsonUtil.toJson(msg));
out.flush();
out.close();
}
}
/**
* 微信H5支付
* 统一下单
* @param request
* @param response
* @param model
* @throws Exception
*/
@RequestMapping("/wxPayH5")
public void wxPayH5(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
//System.out.println("pay ===== start===");
//System.out.println("pay mobile=== " + request.getSession().getAttribute("mobileNumber").toString());
ActOrder actOrder = (ActOrder)request.getSession(true).getAttribute("actOrder");
System.out.println("===wxPayH5===start===actOrder===" + actOrder.toString());
request.getSession().removeAttribute("actOrder");
Map<String, Object> result = new HashMap<String, Object>();
result.put("success", false);
try {
// 付款金额,必填
String total_fee = String.valueOf(actOrder.getTotalPay()); //"0.01"
// 账号信息
String appid = PayConfig.APP_ID; // appid
String mch_id = PayConfig.MCH_ID; // 商业号
String key = PayConfig.API_KEY; // key
String currTime = PayCommonUtil.getCurrTime();
String strTime = currTime.substring(8, currTime.length());
String strRandom = PayCommonUtil.buildRandom(4) + "";
String nonce_str = strTime + strRandom;
// 价格 注意:价格的单位是分
String order_price = new BigDecimal(total_fee).multiply(new BigDecimal(100)).toString().split("\\.")[0];
// 自己网站上的订单号
String out_trade_no = actOrder.getOrderNumber();
// 获取发起电脑 ip
String spbill_create_ip = HttpUtil.getRealIp(request);
// 回调接口
String notify_url = "http://wx.xxx.com/xx/xx/payNotifyMe";
// 页面跳转同步通知页面路径
String trade_type = "MWEB";
// 设置package订单参数
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
packageParams.put("appid", appid);
packageParams.put("mch_id", mch_id);
// 生成签名的时候需要你自己设置随机字符串
packageParams.put("nonce_str", nonce_str);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("total_fee", order_price);
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", trade_type);
packageParams.put("body", PayConfig.BODY);
packageParams.put("scene_info", "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"http://wx.xxxx.com\",\"wap_name\": \"测试\"}}");
String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
System.out.println("订单号:" + out_trade_no + " 的签名:" + sign);
packageParams.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(packageParams);
String resXml = HttpUtil.postData(PayConfig.UFDODER_URL, requestXML);
Map map = XMLUtil.doXMLParse(resXml);
//String urlCode = (String) map.get("code_url");
System.out.println("out_trade_no=" + map.get("out_trade_no"));
System.out.println("prepay_id=" + map.get("prepay_id"));
//确认支付过后跳的地址,需要经过urlencode处理
String urlString = URLEncoder.encode("http://wx.xxx.com/xx/xx/xx/list.html", "GBK");
String mweb_url = map.get("mweb_url")+"&redirect_url="+urlString;
//更新订单状态
actOrder.setPayOrderNO(map.get("prepay_id").toString());
actOrder.setStatement(2);
actOrder.setNote(map.get("sign").toString());
showService.updateOrderStatement(actOrder);
System.out.println("==========mweb_url==========" + mweb_url);
response.sendRedirect(mweb_url);
//result.put("sHtmlText", urlCode);
result.put("success", true);
} catch (Exception e) {
e.printStackTrace();
result.put("errormsg", e.getMessage());
}
}
/**
* 执行回调 确认支付后处理事件 例如添加金额到数据库等操作
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/payNotifyMe")
public void weixin_notify(HttpServletRequest request, HttpServletResponse response, ModelMap model)throws Exception {
System.out.println("进入支付h5回调=====================");
String xmlMsg = readData(request);
System.out.println("pay notice---------"+xmlMsg);
Map params = XMLUtil.doXMLParse(xmlMsg);
try {
// 过滤空 设置 TreeMap
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
Iterator it = params.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = params.get(parameter)+"";
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
//System.out.println( parameter + " value==============="+v);
packageParams.put(parameter, v);
}
//订单号
String orderNO = packageParams.get("out_trade_no").toString().trim();
ActOrder actOrder = new ActOrder();
actOrder.setOrderNumber(orderNO);
actOrder.setPayOrderNO(packageParams.get("sign").toString().trim());
actOrder.setPayOrderNO(packageParams.get("transaction_id").toString());
String resXml = "";
// 处理业务开始
if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
// 这里是支付成功
model.put("msg", "付款成功");
// 执行自己的业务逻辑 更新订单状态
actOrder.setStatement(3);
// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} else {
model.put("msg", "付款失败");
actOrder.setStatement(0);
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[充值失败]]></return_msg>" + "</xml> ";
}
//更新订单
showService.updateOrderStatement(actOrder);
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder result = new StringBuilder();
br = request.getReader();
for (String line; (line=br.readLine())!=null;) {
if (result.length() > 0) {
result.append("\n");
}
result.append(line);
}
return result.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
finally {
if (br != null)
try {br.close();} catch (IOException e) {e.printStackTrace();}
}
}
需要完整的代码可以留言哦!可有偿指导开发完整个流程!
微信H5支付功能开发相关推荐
- 微信H5支付功能小结
微信H5支付整理 官方 流程图 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_3 官方案例 http://wxpay.wxutil. ...
- 微信公众号开发笔记(三):微信JSAPI支付功能开发
很久之前做了微信支付,其中也趟过很多坑,现在有时间就做个自我梳理吧算是. 公众号开发的基本配置(不明白的可以参考https://blog.csdn.net/TOP__ONE/article/detai ...
- 微信APP支付功能开发
前期准备工作 1. 微信各平台功能认识 1.1 微信开放平台: 支持移动应用,公众号的开发,创建应用并得到APPID,使你的应用支持微信支付. 1.2 微信公众平台: 微信小程序,服务号,订阅号的开发 ...
- 微信开发h5支付功能,配置单价和商品信息无法更新问题解决方法!
微信开发h5支付功能,配置单价和商品信息无法更新是因为没有开通h5支付的问题,登录微信商户平台后台开通h5支付产品即可.
- 微信公众号开发,微信支付功能开发(网页JSAPI调用)
1.微信支付的流程 如下三张手机截图,我们在微信网页端看到的支付,表面上看到的是 "点击支付按钮 - 弹出支付框 - 支付成功后出现提示页面",实际上的核心处理过程是: 点击支付按 ...
- 【微信开发第四章】SpringBoot实现微信H5支付
前言 在进行微信公众号业务开发的时候,微信支付可以说是非常重要的一环.该篇文章每一步都有记录,力争理解的同时各位小伙伴也能够实现功能 文章目录 前言 1.公众号配置 2.微信支付实现代码 总结 1.公 ...
- uniapp开发的H5网页,以表单形式调起微信H5支付
一.场景描述: 我们使用uniapp 开发H5网页,嵌入第三方的聚合页,第三方又嵌入另一个app内部 二.技术实现: 1.使用微信H5支付,参考https://pay.weixin.qq.com/wi ...
- 做微信h5支付的统一下单接口开发,虽然已经生成了mweb_url支付链接,但是访问时出现错误提示:‘商家参数格式有误,请联系商家解决’,但是检查h5支付提交的参数,都没有错误。 微信h5支付开发错误
做微信h5支付的统一下单接口开发,虽然已经生成了mweb_url支付链接,但是访问时出现错误提示:'商家参数格式有误,请联系商家解决',但是检查h5支付提交的参数,都没有错误. 后面看到官方文档, 说 ...
- SpringBoot对接微信小程序支付功能开发(一,下单功能)
1,接入前准备: 接入模式选择直连模式: 申请小程序,得到APPID,并开通微信支付: 申请微信商户号,得到mchid,并绑定APPID: 配置商户API key,下载并配置商户证书,根据微信官方文档 ...
- android微信支付都需要什么意思,Android开发微信APP支付功能的要点小结
基本概念 包名值得是你APP的包,在创建工程时候设置的,需要在微信支付平台上面设置. 签名指的是你生成APK时候所用的签名文件的md5,去掉:全部小写,需要在微信支付平台上面设置. 调试阶段,签名文件 ...
最新文章
- 读《大道至简》第六章感想
- 程序员吐槽:非常后悔3年前选择加入互联网行业,因为短期的高工资断送了自己长期的职业生涯发展...
- Linux上安装MongoDB
- 架构 encoder_一种新的超分模型蒸馏架构 (ECCV2020)
- Windows Security——获取Windows已经保存的WiFi网络密码
- sql慢查询问题排查
- Java讲课笔记08:数组
- NumPy Essentials 带注释源码 五、NumPy 中的线性代数
- python实现信号幅值归一化
- 视觉SLAM——ORB-SLAM2运行tum数据集,kitti数据集,euroc数据集
- python 输入中文_【提醒】Python新手开发人员注意事项:不要误输入中文标点符号...
- 【财务预警】基于matlab BP神经网络财务预警【含Matlab源码 494期】
- Win11到底意味着什么
- 转:用AutoCAD 系统变量编程
- 体验魅力Cognos BI 10 系列,第1 部分: 第一次安装
- Ryujinx - 基于 C# 开发的任天堂 Switch 模拟器
- 怎么理解——用户不是人
- ‘gbk‘ codec can‘t decode byte 0xa4 in position 16433: illegal multibyte sequence
- 计算机怎样改成游戏机,手把手教你安装batocera系统,把旧电脑变成万能影音游戏主机...
- 2.3.1 通货膨胀的季节调整与预测模型(pythonR代码复现)
热门文章
- ENVI5.3安装中国国产卫星支持工具
- Javaweb家政服务管理系统的设计与实现
- IDEA 连接 ORACLE 的配置(OJDBC14通过pom配置, OJDBC7通过library配置)
- 【转载】金山词霸”屏幕取词技术揭密(讨论稿)
- DAVINCI DM6446 开发攻略——V4L2视频驱动和应用分析 1
- flash mx拖拽实例_适用于Flash MX 2004 Professional的虹膜和擦除过渡面板
- python 抓取 快代理- 国内高匿代理 IP
- kafka分布式消息系统集群搭建-- 详细过程
- 基于Delphi7的木马程序的查杀设计与实现
- 智能陈桥五笔输入法 for linux,陈桥五笔输入法官方下载