官方文档

准备工作:已通过微信认证的公众号,必须通过ICP备案域名(否则会报支付失败)

借鉴了很多大神的文章,在此先谢过了

整个支付流程,看懂就很好写了

一、设置支付目录

在微信公众平台设置您的公众号支付支付目录,设置路径见下图。公众号支付在请求支付的时候会校验请求来源是否有在公众平台做了配置,所以必须确保支付目录已经正确的被配置,否则将验证失败,请求支付不成功。

支付授权目录就是指支付方法的请求全路径

二、设置授权域名

开发公众号支付时,在统一下单接口中要求必传用户openid,而获取openid则需要您在公众平台设置获取openid的域名,只有被设置过的域名才是一个有效的获取openid的域名,否则将获取失败。具体界面如下图所示:

三、授权进入支付页面

授权部分,我是用的静默授权,拿到openid就好了

授权进入支付页面方法

/** * 静默授权进入H5支付页面 * @return * @throws Exception */
@GetMapping("preJsPay")
public String jsPay( ) throws Exception {  AuthAccessToken authAccessToken = null;  String code = this.getRequest().getParameter("code");if(StringUtils.isEmpty(code)){return "error";}String state = this.getRequest().getParameter("state");  if(state.equals(MD5Util.MD5Encode("ceshi", ""))){AuthTokenParams authTokenParams = new AuthTokenParams();  authTokenParams.setAppid(WechatConfig.APP_ID);authTokenParams.setSecret(WechatConfig.APP_SECRET);  authTokenParams.setCode(code);authAccessToken = wechatAuthService.getAuthAccessToken(authTokenParams, null);logger.debug("正在支付的openid {} "   ,authAccessToken.getOpenid());  return "wxpay/jspay";}return "error";
}  

支付页面的的body(这是原先的jsp页面,目前我改成了thymeleaf,或者改写成vue、ng)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<title>微信支付</title>
</head>
<body><h3 class="demos-title" style="margin-bottom: 50px; margin-top: 50px">测试</h3><div class="weui_cell"></div><div class="weui_btn_area" style="margin-top: 80px"><input class="weui_btn weui_btn_primary" type="button" value="点击支付" onclick="pay()"/></div><script type="text/javascript">var prepay_id ;var paySign ;var appId ;var timeStamp ;var nonceStr ;var packageStr ;var signType ;function pay(){var url = '${ctx}/wxpay/jspay';$.ajax({type:"post",url:url,dataType:"json",data:{openId:'${openId}'}, //自行拼接body,total_fee等参数success:function(data) {if(data.data.resultCode == 'SUCCESS'){appId = data.appId;paySign = data.paySign;timeStamp = data.timeStamp;nonceStr = data.nonceStr;packageStr = data.packageStr;signType = data.signType;callpay();}else{alert("统一下单失败");}}}); }function onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest', {"appId":appId,     //公众号名称,由商户传入"paySign":paySign,         //微信签名"timeStamp":timeStamp, //时间戳,自1970年以来的秒数"nonceStr":nonceStr , //随机串"package":packageStr,  //预支付交易会话标识"signType":signType     //微信签名方式},function(res){if(res.err_msg == "get_brand_wcpay_request:ok" ) {//window.location.replace("index.html");alert('支付成功');}else if(res.err_msg == "get_brand_wcpay_request:cancel"){alert('支付取消');}else if(res.err_msg == "get_brand_wcpay_request:fail" ){alert('支付失败');} //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。});}function callpay(){if (typeof WeixinJSBridge == "undefined"){if( document.addEventListener ){document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);}else if (document.attachEvent){document.attachEvent('WeixinJSBridgeReady', onBridgeReady);document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);}}else{onBridgeReady();}}
</script>
</body>
</html>

四、统一下单并获取prepay_id并返回页面支付参数

统一下单的官方文档,prepay_id获取到就是成功了一半了

由于我是用的restcontroller,返回的类型你可以改成JsPayResult

 /*** 微信内H5调起支付** @param params* @return* @throws Exception*/@PostMapping("js")public Map<String, Object> js(HttpServletRequest request, @ModelAttribute(value = "params") UnifiedOrderParams params) {Map<String, Object> data = new HashMap<>();if (StringUtils.isEmpty(params) || StringUtils.isEmpty(params.getOpenid())) {data.put("code", -1);data.put("msg", "支付数据错误");return data;}log.debug("****正在支付的openId****{}", params.getOpenid());// 统一下单String out_trade_no = PayHelper.createOutTradeNo();// int total_fee = 1; // 产品价格1分钱,用于测试String spbill_create_ip = HttpUtil.getRemortIP(request);log.debug("支付IP {} ", spbill_create_ip);String nonce_str = PayHelper.createNonceStr(); // 随机数据// 参数组装UnifiedOrderParams unifiedOrderParams = new UnifiedOrderParams();unifiedOrderParams.setAppid(wechatAccountConfig.getAppid());// 必须unifiedOrderParams.setMch_id(PayConstant.MCH_ID);// 必须unifiedOrderParams.setOut_trade_no(out_trade_no);// 必须unifiedOrderParams.setBody(params.getBody());// 必须 微信支付-支付测试unifiedOrderParams.setTotal_fee(params.getTotal_fee()); // 必须unifiedOrderParams.setNonce_str(nonce_str); // 必须unifiedOrderParams.setSpbill_create_ip(spbill_create_ip); // 必须unifiedOrderParams.setTrade_type("JSAPI"); // 必须unifiedOrderParams.setOpenid(params.getOpenid());unifiedOrderParams.setNotify_url(wechatPayConfig.getNotifyUrl());// 异步通知url// 统一下单 请求的Xml(正常的xml格式)String unifiedXmL = PayHelper.toPayXml(unifiedOrderParams);// 签名并入util// 进行签名校验try {// 返回<![CDATA[SUCCESS]]>格式的XMLString unifiedOrderResultXmL = HttpUtil.doPost(wechatPayConfig.getUnifiedOrderUrl(), null, unifiedXmL);if (SignatureUtil.checkValidPaySign(unifiedOrderResultXmL, null)) {String timeStamp = PayHelper.createTimeStamp();// 统一下单响应UnifiedOrderResult unifiedOrderResult = XmlUtil.fromXml(unifiedOrderResultXmL,UnifiedOrderResult.class);JsPayResult result = new JsPayResult();result.setAppId(wechatAccountConfig.getAppid());result.setTimeStamp(timeStamp);result.setNonceStr(unifiedOrderResult.getNonce_str());// 直接用返回的/**** prepay_id 2小时内都有效,再次支付方法自己重写 ****/result.setPackageStr("prepay_id=" + unifiedOrderResult.getPrepay_id());/**** 用对象进行签名 ****/String paySign = SignatureUtil.md5Hex(result, PayConstant.API_KEY,null);result.setPaySign(paySign);result.setResultCode(unifiedOrderResult.getResult_code());data.put("code", 0);data.put("msg", "支付成功");data.put("data", result);} else {data.put("code", -1);data.put("msg", "支付签名验证错误");log.debug("签名验证错误");}} catch (Exception e) {data.put("code", -1);data.put("msg", "支付失败");log.debug(e.getMessage());}return data;}

五、完成支付并通知支付结果

支付通知结果

package com.phil.wechat.pay.controller;import com.phil.modules.result.ResultState;
import com.phil.modules.util.SignatureUtil;
import com.phil.modules.util.XmlUtil;
import com.phil.wechat.pay.model.response.PayNotifyResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.util.Objects;/*** 微信支付结果通知(统一下单参数的notify_url)** @author phil* @date 2017年6月27日*/
@RestController
@RequestMapping("api/wxpay")
@Slf4j
public class WechatPayNotifyController {@RequestMapping("notify")public ResultState notice(HttpServletRequest request, HttpServletResponse response) throws Exception {ResultState resultState = new ResultState();log.debug("开始处理支付返回的请求");String resXml = ""; // 反馈给微信服务器String notifyXml = IOUtils.toString(request.getInputStream());// 微信支付系统发送的数据(<![CDATA[product_001]]>格式)log.debug("微信支付系统发送的数据" + notifyXml);// 验证签名if (SignatureUtil.checkValidPaySign(notifyXml, null)) {PayNotifyResult notify = XmlUtil.fromXml(notifyXml, PayNotifyResult.class);log.debug("支付结果 {}", notify.toString());if (Objects.equals("SUCCESS", notify.getResult_code())) {resultState.setErrcode(0);// 表示成功resultState.setErrmsg(notify.getResult_code());/**** 业务逻辑 保存openid之类的 ****/// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";} else {resultState.setErrcode(-1);// 支付失败resultState.setErrmsg(notify.getErr_code_des());log.debug("支付失败,错误信息:" + notify.getErr_code_des());resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA["+ notify.getErr_code_des() + "]]></return_msg>" + "</xml> ";}} else {resultState.setErrcode(-1);// 支付失败resultState.setErrmsg("签名验证错误");log.debug("签名验证错误");resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"+ "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";}try (BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream())) {out.write(resXml.getBytes());out.flush();} catch (Exception e) {log.error(e.getMessage());}return resultState;}
}

具体源码:https://github.com/philjing/my_wechat/tree/master/src/main/java/com/phil/wechat/pay

Java微信支付开发之公众号支付(微信内H5调起支付)相关推荐

  1. java微信公众号支付开发平台_Java微信公众平台开发之公众号支付(微信内H5调起支付)...

    官方文档 准备工作:已通过微信认证的公众号,必须通过ICP备案域名(否则会报支付失败) 借鉴了很多大神的文章,在此先谢过了 整个支付流程,看懂就很好写了 一.设置支付目录 在微信公众平台设置您的公众号 ...

  2. 微信支付开发教程(公众号支付)

    前段时间公司电商项目需要接入微信支付,因此研究了一下如何使用微信支付.和支付宝支付相比,微信支付相对复杂一些,需要配置的东西更多,限制也更多.经过两天的研究,终于搞定微信支付,在这里对于使用微信支付的 ...

  3. java微信内h5调起支付_java微信支付--------公众号内H5调起支付

    /*** 统一下单接口,获取prepay_id *@paramrequest *@return */@RequestMapping(value= "/unifiedOrder", ...

  4. java微信内h5调起支付_java进行微信h5支付开发

    最近在做微信支付开发用的框架是 srpingMVC mybatis spring 下面是开发流程图 我们只需要开发红色标记的模块就可以了. 具体参数详情可以查看微信开发者文档. 新手第一次写,写的不好 ...

  5. 微信商城开发:公众号平台接口配置及调试

    <微信商城开发系列教程第二讲> 公众号平台接口配置及调试 [本系列文章转载自:walkingmanc(作者:陈伟)] 在上一篇中,我们讲解了如何申请微信公众号,公众平台开发的基本原理以及服 ...

  6. h5微信本地调试 vue_Vue 移动端微信内H5调起支付(利用js sdk)

    前端的写法 1.封装wxPay.js import wx from 'weixin-js-sdk' //先下载后引入 export function wexinPay(data) { return n ...

  7. 微信支付之微信内H5调起支付

    微信支付主要就是 1.openId的获取 2.订单详情扩展字符串prepay_id的获取 3.签名paySign的生成 1.有订单号(tradeNo),openId以及金额(totalfee) 其中订 ...

  8. 微信h5 签名错误 php,【微信jsApi 支付】微信内H5调起支付时,提示“验证签名失败”...

    1) 使用微信的在线签名工具检查签名是否和程序生成的一致 选择MD5,XML,然后把请求参数xml放进去,就能校验签名. 2)如果和微信的在线签名工具一致,说明程序没有错误,确定是API密钥错误(被别 ...

  9. JAVA版开源微信管家—JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗

    支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1--多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗) JeeWx捷微V3.1.0版本紧跟微信小程序更新,在原有 ...

最新文章

  1. 精读《手写 SQL 编译器 - 错误提示》
  2. html5+开发移动app
  3. 文计笔记 4 字符编码与数制
  4. Linux日志查看head与tail配合查看区间行数的内容
  5. http 状态码 504 502
  6. 前端学习(2864):简单秒杀系统学习之优化js
  7. android layout_width 属性,android:layout_weight属性详解
  8. 在Struts结构中,JSP页面的元件命名最好别用大写字母开头
  9. 快速部署与收回解决方案包
  10. android开发realm多线程操作,数据库的设计:深入理解 Realm 的多线程处理机制
  11. 【动态规划】牛客网:把数字翻译成字符串
  12. Docker镜像源更改
  13. Android热修复技术初探(三):动态加载外部资源
  14. vue+django2.0.2-rest-framework 生鲜项目(五)
  15. 关于Activity跳转动画大汇总
  16. css实现手风琴图片特效
  17. java二维码之生成与解析
  18. MySQL -- 插入56个民族
  19. 2022数据结构习题(知产)
  20. 【人工智能 卷积神经网络】基础练习:基于torch构建卷积神经网络,测试集正确率达 百分之99

热门文章

  1. yb3防爆电机型号含义_防爆电机型号及防爆标志的意义
  2. Electron教程(三)如何打包 electron 程序:electron-forge 的使用教程
  3. 计算机网络实验 局域网的组建,计算机网络实验-局域网组建及测试实验
  4. Ceph MDS问题分析
  5. 视频教程-像TED演讲:如何做一个一份优秀的PPT -Office/WPS
  6. 过滤三角网算法求取凹包(二)
  7. python导入数据聚类分析实例_聚类分析实战解析与总结 - 数据分析
  8. 手机录制的视频不能导入AE解决办法,86::1,先导入PR
  9. docker可以把应用及其相关的_Docker及其相关技术
  10. 最新UPX3.91-支持win64/PE-加/脱壳