微信H5支付功能开发

news/2024/11/19 11:42:00/

本文介绍的是微信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();}

}

}

需要完整的代码可以留言哦!可有偿指导开发完整个流程!

 


http://www.ppmy.cn/news/161772.html

相关文章

公众号H5微信生态

做个近期微信生态的总结 所有的前提是在微信公众平台 登录对应的微信公众号 公众号上配置对应的h5域名。 包括支付 分享等&#xff08;可自行百度 很多这种教程 官方文档也有搜索微信支付配置 里面有公众号配置等&#xff09; 首先是微信授权。主要拿用户的openId 进行支付操…

H5和HTML5的区别

注意注意&#xff1a;H5不HTML5 H5 是一个产品名词 HTML5是一个技术名词 对于知乎多个相关问题里批判H5的叫法&#xff0c;我只想说&#xff1a;图样图森破&#xff0c;上台拿衣服 打个比方&#xff0c;如果有个人跟你说&#xff1a;“我要做个网站&#xff0c;H5的”。 那TA是…

H5,Audio音乐播放器(移动版)

有些时候&#xff0c;总是感觉自己进步的没有以前快了。于是就怀疑自己是不是也被时间磨灭了&#xff0c;这可真是一件不幸的事儿。可能是自己会的东西太少了&#xff0c;总是有种莫名的危机感。 前一段时间&#xff0c;想写一个移动版音乐播放器&#xff0c;于是就开始利用下班…

微信H5开发(一)

H5开发&#xff0c;一般是指移动端的页面开发。移动端可分为app和普通浏览页面。从嵌入的环境来归类&#xff1a;可以分为app、微信H5及手机浏览器里面打开的页面。 以前粗略的涉略过h5开发的一些知识&#xff0c;感觉H5并不是很难。在这半年内&#xff0c;接手并完成了两个微…

惠威试音碟高品质MP3版

01、雪花飞扬/郭峰 电子合成器 02、试音方程式/女声清唱 03、Shania Fuain/Shania Twain 《诺丁山》的主题曲 04、渡口 蔡琴/流行歌曲 05、达坂城姑娘/八只眼 男声合唱 06、加州旅店/老鹰乐队 07、鼓诗/闫学敏 炎黄第一鼓 08、红灯记/京剧女声 09、张三的歌/蔡琴 流行歌…

微信公众号内嵌的H5页面

前言&#xff1a;之前写微信端购物商城的页面时&#xff0c;使用过flex布局&#xff0c;方便灵活&#xff0c;对手机端兼容性良好&#xff0c;同时可应对复杂的嵌套布局&#xff0c;很是方便。但是&#xff0c;针对两栏式的微信端页面&#xff0c;除了flex布局&#xff0c;还有…

H5与web的区别?

&#xff08;区分app里面嵌入的h5&#xff0c;或者是web端嵌入的h5&#xff0c;我先说下APP端嵌入的h5和web端相同的&#xff09;&#xff0c;h5和web&#xff0c;从测试流程来讲&#xff0c;它们的主流程是一样的&#xff0c;都是要经过需求分析、评审、案例编写、测试bug跟踪…

微信支付 ——H5支付

先看下微信官方描述的H5支付应用场景&#xff1a; H5支付是指商户在微信客户端外的移动端网页展示商品或服务&#xff0c;用户在前述页面确认使用微信支付时&#xff0c;商户发起本服务呼起微信客户端进行支付。 主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外…