一,问题

这两天,需要接入微信支付功能。由于我是公众号开发,因此,我选择的微信支付方式是JSAPI支付方式。

二,解决方案

2.1 配置微信平台

①配置微信公众平台

登录微信公众平台=》公众号设置=》功能设置=》网页授权域名

②配置微信商家平台

产品中心=》开发配置

2.2 后台代码的实现

JSAPI官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

①先去官方下载SDK,并导进项目中

地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

②准备好11个参数

appid:商家平台ID。在微信的平台上有
body:商品描述。
mch_id:商户ID。在微信的平台上有
nonce_str:随机字符串,UUID就好了。
openid:用户标识。因为这边是用户已经登录成功了。所以在session中就能拿到。
out_trade_no:商户订单号
spbill_create_ip:终端IP。这个可以从请求头中拿到
total_fee:支付金额。单位是分。
trade_type:交易类型。这里我填JSAPI
notify_url:通知地址。就是用户支付成功之后,微信访问你的哪个接口,跟你传递支付成功的相关信息。
sign:签名。这个签名它是由上面的10个参数计算得出的。

③源码
sendPay类:

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.http.auth.AUTH;
import org.hamcrest.core.Is;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import com.jc.util.wxPay.WXPayUtil;
import com.sun.xml.internal.fastinfoset.Encoder;import controller.AuthUtil;
import net.sf.json.JSONObject;@Controller
@RequestMapping("/pay")
public class sendPay {/*** @Description 微信浏览器内微信支付/公众号支付(JSAPI)* @param request* @param code* @return Map*/@RequestMapping(value = "orders")public @ResponseBody Map<String, String> orders(HttpServletRequest request, HttpServletResponse response) {try {String openId = "用户的openid";// 拼接统一下单地址参数Map<String, String> paraMap = new HashMap<String, String>();// 获取请求ip地址String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}if (ip.indexOf(",") != -1) {String[] ips = ip.split(",");ip = ips[0].trim();}paraMap.put("appid", AuthUtil.APPID); // 商家平台IDparaMap.put("body", "纯情小店铺-薯条"); // 商家名称-销售商品类目、String(128)paraMap.put("mch_id", AuthUtil.MCHID); // 商户IDparaMap.put("nonce_str", WXPayUtil.generateNonceStr()); // UUIDparaMap.put("openid", openId);paraMap.put("out_trade_no", UUID.randomUUID().toString().replaceAll("-", ""));// 订单号,每次都不同paraMap.put("spbill_create_ip", ip);paraMap.put("total_fee", "1"); // 支付金额,单位分paraMap.put("trade_type", "JSAPI"); // 支付类型paraMap.put("notify_url", "用户支付完成后,你想微信调你的哪个接口");// 此路径是微信服务器调用支付结果通知路径随意写String sign = WXPayUtil.generateSignature(paraMap, AuthUtil.PATERNERKEY);paraMap.put("sign", sign);String xml = WXPayUtil.mapToXml(paraMap);// 将所有参数(map)转xml格式// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorderString unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";System.out.println("xml为:" + xml);// String xmlStr = HttpRequest.sendPost(unifiedorder_url,// xml);//发送post请求"统一下单接口"返回预支付id:prepay_idString xmlStr = HttpRequest.httpsRequest(unifiedorder_url, "POST", xml);System.out.println("xmlStr为:" + xmlStr);// 以下内容是返回前端页面的json数据String prepay_id = "";// 预支付idif (xmlStr.indexOf("SUCCESS") != -1) {Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);prepay_id = (String) map.get("prepay_id");}Map<String, String> payMap = new HashMap<String, String>();payMap.put("appId", AuthUtil.APPID);payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");payMap.put("nonceStr", WXPayUtil.generateNonceStr());payMap.put("signType", "MD5");payMap.put("package", "prepay_id=" + prepay_id);String paySign = WXPayUtil.generateSignature(payMap, AuthUtil.PATERNERKEY);payMap.put("paySign", paySign);//将这个6个参数传给前端return payMap;} catch (Exception e) {e.printStackTrace();}return null;}/*** @Title: callBack* @Description: 支付完成的回调函数* @param:* @return:*/@RequestMapping("/notify")public String callBack(HttpServletRequest request, HttpServletResponse response) {// System.out.println("微信支付成功,微信发送的callback信息,请注意修改订单信息");InputStream is = null;try {is = request.getInputStream();// 获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)String xml = WXPayUtil.InputStream2String(is);Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);// 将微信发的xml转mapSystem.out.println("微信返回给回调函数的信息为:"+xml);if (notifyMap.get("result_code").equals("SUCCESS")) {String ordersSn = notifyMap.get("out_trade_no");// 商户订单号String amountpaid = notifyMap.get("total_fee");// 实际支付的订单金额:单位 分BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);// 将分转换成元-实际支付金额:元/** 以下是自己的业务处理------仅做参考 更新order对应字段/已支付金额/状态码*/System.out.println("===notify===回调方法已经被调!!!");}// 告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");} catch (Exception e) {e.printStackTrace();} finally {if (is != null) {try {is.close();} catch (IOException e) { e.printStackTrace();}}}return null;}}

HttpRequest类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;import javax.net.ssl.HttpsURLConnection;public class HttpRequest {/*** 向指定URL发送GET方法的请求* * @param url*            发送请求的URL* @param param*            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。* @return URL 所代表远程资源的响应结果*/public static String sendGet(String url, String param) {String result = "";BufferedReader in = null;try {String urlNameString = url + "?" + param;System.out.println(urlNameString);URL realUrl = new URL(urlNameString);// 打开和URL之间的连接URLConnection connection = realUrl.openConnection();// 设置通用的请求属性connection.setRequestProperty("accept", "*/*");connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 建立实际的连接connection.connect();// 获取所有响应头字段Map<String, List<String>> map = connection.getHeaderFields();// 遍历所有的响应头字段for (String key : map.keySet()) {System.out.println(key + "--->" + map.get(key));}// 定义 BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {System.out.println("发送GET请求出现异常!" + e);e.printStackTrace();}// 使用finally块来关闭输入流finally {try {if (in != null) {in.close();}} catch (Exception e2) {e2.printStackTrace();}}return result;}/*** 向指定 URL 发送POST方法的请求* * @param url*            发送请求的 URL* @param param*            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。* @return 所代表远程资源的响应结果*/public static String sendPost(String url, String param) {PrintWriter out = null;BufferedReader in = null;String result = "";try {URL realUrl = new URL(url);// 打开和URL之间的连接URLConnection conn = realUrl.openConnection();// 设置通用的请求属性conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");// 发送POST请求必须设置如下两行conn.setDoOutput(true);conn.setDoInput(true);// 获取URLConnection对象对应的输出流out = new PrintWriter(conn.getOutputStream());// 发送请求参数out.print(param);// flush输出流的缓冲out.flush();// 定义BufferedReader输入流来读取URL的响应in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));String line;while ((line = in.readLine()) != null) {result += line;}} catch (Exception e) {System.out.println("发送 POST 请求出现异常!" + e);e.printStackTrace();}// 使用finally块来关闭输出流、输入流finally {try {if (out != null) {out.close();}if (in != null) {in.close();}} catch (IOException ex) {ex.printStackTrace();}}return result;}/*** post请求并得到返回结果* * @param requestUrl* @param requestMethod* @param output* @return*/public static String httpsRequest(String requestUrl, String requestMethod, String output) {try { URL url = new URL(requestUrl);HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();connection.setDoOutput(true);connection.setDoInput(true);connection.setUseCaches(false);connection.setRequestMethod(requestMethod);if (null != output) {OutputStream outputStream = connection.getOutputStream();outputStream.write(output.getBytes("UTF-8"));outputStream.close();}// 从输入流读取返回内容InputStream inputStream = connection.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;connection.disconnect();return buffer.toString();} catch (Exception ex) {ex.printStackTrace();}return "";}
}

AuthUtil类

import java.io.IOException;import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;import net.sf.json.JSONObject;
public class AuthUtil {public static final String APPID = "平台ID";public static final String APPSECRET = "平台密钥";public static final String MCHID = "商家ID";public static final String PATERNERKEY = "商家密钥";public static JSONObject doGetJson(String url) throws ClientProtocolException, IOException {JSONObject jsonObject = null;// 首先初始化HttpClient对象DefaultHttpClient client = new DefaultHttpClient();// 通过get方式进行提交HttpGet httpGet = new HttpGet(url);// 通过HTTPclient的execute方法进行发送请求HttpResponse response = client.execute(httpGet);// 从response里面拿自己想要的结果HttpEntity entity = response.getEntity();if (entity != null) {String result = EntityUtils.toString(entity, "UTF-8");jsonObject = jsonObject.fromObject(result);}// 把链接释放掉httpGet.releaseConnection();return jsonObject;}
}

2.3 前端的实现

这是只用一个jsp页面来做测试

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="./js/jquery-1.11.0.min.js"></script>
<title>微信支付JSP</title>
</head>
<body> <input type="button" value="进行微信支付" id="payId"><script type="text/javascript">$(function(){var appId,timeStamp,nonceStr,package,signType,paySign; $("#payId").click(function(){pay();});//去后台拿六个参数function pay(){   var url = "http://localhost:8082/WeChat/pay/orders";$.get(url,function(result) {  appId = result.appId;timeStamp = result.timeStamp;nonceStr = result.nonceStr;package = result.package;signType = result.signType;paySign = result.paySign;if (typeof WeixinJSBridge == "undefined") {if (document.addEventListener) {document.addEventListener('WeixinJSBridgeReady',onBridgeReady, false);} else if (document.attachEvent) {document.attachEvent('WeixinJSBridgeReady',onBridgeReady);document.attachEvent('onWeixinJSBridgeReady',onBridgeReady);}alert("请在微信上进行支付操作!");onBridgeReady();} else { onBridgeReady();}});}//去微信那边发起支付请求function onBridgeReady(){alert("appId:"+appId+" "+"timeStamp:"+timeStamp+" "+"nonceStr:"+nonceStr+" "+"package:"+package+" "+"signType:"+signType+" "+"paySign:"+paySign+" ");WeixinJSBridge.invoke( 'getBrandWCPayRequest', {"appId":appId,     //公众号名称,由商户传入     "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数     "nonceStr":nonceStr, //随机串     "package":package,     "signType":signType,         //微信签名方式:     "paySign":paySign //微信签名 }, function(res){      if(res.err_msg == "get_brand_wcpay_request:ok" ) {//alert('支付成功');console.log("支付成功");//支付成功后跳转的页面}else if(res.err_msg == "get_brand_wcpay_request:cancel"){alert('支付取消');}else if(res.err_msg == "get_brand_wcpay_request:fail"){alert('支付失败');alert(JSON.stringify(res));WeixinJSBridge.call('closeWindow');} //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。});    }})
</script></body>
</html>

三,总结

虽然第一次看官方文档很乱,信息量很多,但仔细总结一下,其实就下面这点流程而已。

最后,很感谢网上一位大哥分享了他的经验。
大哥链接:https://blog.csdn.net/javaYouCome/article/details/79473743

JAVA实现微信支付功能相关推荐

  1. 微信小程序-JAVA实现微信支付功能(微信支付2.0)

    微信小程序-JAVA实现微信支付功能(微信支付2.0) 一.前言 本博客主要介绍JAVA后台与微信小程序(UNI-APP或者原生微信小程序)的微信支付的实现,如果是APP或者H5的开发暂时不支持,具体 ...

  2. 微信公众号开发,微信支付功能开发(网页JSAPI调用)

    1.微信支付的流程 如下三张手机截图,我们在微信网页端看到的支付,表面上看到的是 "点击支付按钮 - 弹出支付框 - 支付成功后出现提示页面",实际上的核心处理过程是: 点击支付按 ...

  3. 【javaWeb微服务架构项目——乐优商城day15】——会调用订单系统接口,实现订单结算功能,实现微信支付功能

    0.学习目标 会调用订单系统接口 实现订单结算功能 实现微信支付功能 源码笔记及资料: 链接:https://pan.baidu.com/s/1_opfL63P1pzH3rzLnbFiNw 提取码:v ...

  4. php android 微信支付,Android_Android实现微信支付功能,开发Android APP微信支付功能, - phpStudy...

    Android实现微信支付功能 开发Android APP微信支付功能,需要完成三个步骤:第一步生成预支付订单.第二步生成微信支付参数.第三步调起微信APP支付.除了需要审核通过的APP应用外,还需要 ...

  5. springboot 微信小程序 对接微信支付功能(完整版)

    微信小程序对接微信支付功能 业务流程时序图 JAVA版 1. 项目架构 2. pom.xml配置文件 3. 小程序账号参数配置类 4.JAVA 通用代码 4.1 工具类 4.1.1 IdGen (id ...

  6. java集成微信支付接口(微信V3版)

    吐槽下: 经常有人问我,你不是在某软件公司么?我听说大公司都是JAVA,对吗? 我只想回答,那是网上流传的骗人的传说,据我所知公司开发组大部分都是C#,少部分用JAVA. 这不,官方提供那个Demo就 ...

  7. 微信小程序中嵌套html_微信小程序:web-view嵌套H5实现微信支付功能解决方案及填坑...

    ab7117c7d4947210c39e126a01d23ede.jpg 最近一个多月加班比较严重,偶尔休息一天也是在补睡眠+陪家人,比较长时间没有来进行总结记录了.今天不加班,开始为这段时间做的东西 ...

  8. 如何使用easywechat开发微信支付功能

    easywechat是神一样的存在.非常好用.希望大家都能转到这上面来. 用easywechat来开发微信支付功能,步骤如下: 一,需要有一个商品下单页面,页面上有你的商品的信息,还要有购买数量,和一 ...

  9. java对接微信支付收不到支付通知问题(亲身实践)

    问题描述: 用java对接微信支付时,统一下单接口正常.但是用户扫码付款成功后,设置用于回调的notify_url对应的接口并没有收到请求(这个url测试过,是正常的且外网能访问的). 由于官方文档没 ...

  10. 尚医通项目150-170:预约挂号、微信支付功能

    前台用户系统 预约挂号 1.接口分析 (1)根据预约周期,展示可预约日期数据,按分页展示 (2)选择日期展示当天可预约列表(该接口后台已经实现过) 2.页面展示分析 (1)分页展示可预约日期,根据有号 ...

最新文章

  1. 2022-2028年中国商业综合体行业市场前瞻与投资规划分析报告
  2. Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)【转】...
  3. MyBatis-学习笔记10【10.JNDI扩展知识】
  4. Cloud Foundry Java客户端–流事件
  5. asp怎么循环增加字段和字段对应的值_索引该怎么创建?
  6. jquery选择器_jQuery选择器
  7. 用python完成《商务与经济统计(第13版)》课后练习——第九章
  8. DFA敏感词过滤算法详解
  9. 电脑运行c语言程序就蓝屏,常见电脑蓝屏代码,产生原因和解决办法
  10. [全国十大城市火车票售票点、订票电话(买票再也不用去火车站排队)] – [旅游] – [校内论坛]
  11. 黑马程序员—一张帖看完黑马所有学科、班级就业薪资贴
  12. MySQL-查询本周过生日的人-终极答案
  13. mysql todate日期格式写法_MYSQL的日期格式date_format用法
  14. 2021全国高校计算机能力挑战赛程序设计赛Python组区域赛(初赛)试题及部分个人解答
  15. 【鼠标事件 MouseEvent】clientX clientY offsetX offsetX pageX screenX screenY
  16. 中央电大 c语言程序设计a 试题,中央电大2008年秋C语言程序设计A试题5
  17. Android Drawable设计圆角
  18. 腾讯区块链团队首次换将,蔡弋戈将变动职务
  19. java计算机毕业设计医院病历管理系统源程序+mysql+系统+lw文档+远程调试
  20. js中国标准时间转换为yyyy-MM-dd

热门文章

  1. semilogx 多条曲线_如何在excel中绘制多条曲线
  2. c语言中变量要加引号吗,CMake中引号用法总结
  3. bayaim_今晚打老虎
  4. 银行与第三方支付平台的竞合关系分析
  5. 宠物卡牌大赛奖励发放结束公告
  6. pytorch 介绍
  7. C/C++ 常用程序库
  8. Ant design分析后台首页
  9. 用max的角度来解析blender建模!
  10. 软件渗透测试:定义、需求、过程