https://www.cnblogs.com/gopark/p/9394951.html,这篇文章写的已经很详细了。

下面写一下自己的思路:

1.首先下载demo,地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

2.demo中很多方法对于公众号支付用不到,不需要全都看

3.主要是获取11个参数,放到Map中,用demo里提供WXPayUtil.mapToXml方法转为XML格式,通过post方法请求微信端的统一下单接口,后台收到微信传过来的XML字符串,通过WXPayUtil.xmlToMap方法转为Map,根据key值,获取prepay_id(预支付ID),再把需要的6个参数放到Map中,发送给前台,前台根据prepay_id,唤起微信支付,完成付款。

4.11个参数跟6个参数在controller里面都有写,重点的是:openid

5.查看订单,取消订单等其他功能,后续接触到再进行更新

下面放上自己写的controller

 package com.github.wxpay.controller;

 import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.github.wxpay.util.Constant;
import com.github.wxpay.util.HttpRequestUtil;
import com.github.wxpay.util.OrderUtil;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.RequestMapping;
import com.github.wxpay.sdk.WXPayConstants.SignType; public class WxPayController { /**
*
* @Description 微信浏览器内微信支付/公众号支付(JSAPI)
*/
@RequestMapping(value = "/orders",method = RequestMethod.GET)
@ResponseBody
public Map orders(HttpServletRequest request){
try {
Map<String, String> paramMap = new HashMap<String, String>();
HttpSession session = request.getSession();
String wxopenid = session.getAttribute("openid") == null ? null : session.getAttribute("openid").toString();
//在商户平台的账户中心下:需要用户自行下载证书及安装
String key = Constant.signCustomerKey;
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();
}
paramMap.put("appid", Constant.APPIDS[0]);
paramMap.put("mch_id", "");
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
paramMap.put("body", "测试订单XX矿泉水");
paramMap.put("openid", wxopenid);
paramMap.put("out_trade_no", OrderUtil.orderNumber());
paramMap.put("spbill_create_ip", ip);
paramMap.put("total_fee", "0.01");
paramMap.put("notify_url", "http://127.0.0.1:8080/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp");// 此路径是微信服务器调用支付结果通知路径
paramMap.put("trade_type", "JSAPI");
String sign = WXPayUtil.generateSignature(paramMap,key,SignType.MD5);
paramMap.put("sign", sign); // 将所有参数(map)转xml格式
String mapToXml = WXPayUtil.mapToXml(paramMap);
System.out.println(mapToXml);
// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
// 发送post请求"统一下单接口"返回预支付id:prepay_id
String xmlStr = HttpRequestUtil.sendPost(unifiedorder_url,mapToXml); Map<String,String> XmlToMap = WXPayUtil.xmlToMap(xmlStr);
// 以下内容是返回前端页面的json数据
String prepay_id = ""; // 预支付ID
if (xmlStr.indexOf("SUCCESS") != -1) {
Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
prepay_id = map.get("prepay_id");
}
Map<String, String> payMap = new HashMap<String, String>();
XmlToMap.put("appId", Constant.APPIDS[0]);
XmlToMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");
XmlToMap.put("nonceStr", WXPayUtil.generateNonceStr());
XmlToMap.put("signType", "MD5");
XmlToMap.put("package", "prepay_id=" + prepay_id);
String paySign = WXPayUtil.generateSignature(payMap, key);
payMap.put("paySign", paySign);
return XmlToMap;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}

httpRequest工具:

 package com.github.wxpay.util;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URLConnection;
import java.util.List;
import java.net.URL;
import java.util.Map; public class HttpRequestUtil {
/**
* 向指定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;
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()));
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;
}
}

随机数工具:

package com.github.wxpay.util;

import com.github.wxpay.sdk.WXPayUtil;

public class OrderUtil {

    public static String orderNumber(){
int r1 = (int)(Math.random()*10);
int r2 = (int)(Math.random()*10);
long now = WXPayUtil.getCurrentTimestampMs();
String paymentID = String.valueOf(r1)+String.valueOf(r2)+String.valueOf(now);
return paymentID;
}
}

java开发微信公众号支付(JSAPI)的更多相关文章

  1. Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token

    获取access_token是微信api最重要的一个部分,因为调用其他api很多都需要用到access_token.比如自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等在请求的时候 ...

  2. Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

    在前几节文章中我们讲述了微信公众号环境的搭建.如何接入微信公众平台.以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装:接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这 ...

  3. Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装

    在前面几篇文章我们讲了微信公众号环境的配置 和微信公众号服务的接入,接下来我们来说一下微信服务器请求消息,响应消息以及事件消息的相关内容,首先我们来分析一下消息类型和返回xml格式及实体类的封装. ( ...

  4. Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发

    接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 资料准备: 1.一个可以访问的外网,即80的访问端口,因为微信公众号接 ...

  5. Java开发微信公众号(一)---初识微信公众号以及环境搭建

    ps:1.开发语言使用Java springMvc+Mybaits+spring maven实现 2.使用微信接口测试账号进行本地测试 https://mp.weixin.qq.com/debug/c ...

  6. java版微信公众号支付(H5调微信内置API)

    最近需要做微信公众号支付,网上找了大堆的代码,大多都只说了个原理,自己踩了太多坑,所有的坑,都会再下面的文章中标注,代码我也贴上最全的(叫我雷锋)!!! 第一步:配置支付授权目录 你需要有将你公司的微 ...

  7. 微信公众号支付JSAPI网页,total_fee错误不正确,header重定向参数丢失,无法获取订单号和金额解决

    微信公众号支付官方demo错误, 公众号支付只能用在微信里,也就是微信内部浏览器. 1.到WxPayHubHelper.php文件 JsApi_pub()类下createOauthUrlForCode ...

  8. 用java开发微信公众号:测试公众号与本地测试环境搭建(一)

    本文为原创,原始地址为:http://www.cnblogs.com/fengzheng/p/5023678.html 俗话说,工欲善其事,必先利其器.要做微信公众号开发,两样东西不可少,那就是要有一 ...

  9. Java 关于微信公众号支付总结附代码

    很多朋友第一次做微信支付的时候都有蒙,但当你完整的做一次就会发现其实并没有那么难 业务流程和应用场景官网有详细的说明:https://pay.weixin.qq.com/wiki/doc/api/js ...

随机推荐

  1. 关于Tool接口--------hadoop接口:extends Configured implements Tool 和 ToolRunner.run

    我们在写Hadoop--map/reduce程序时,遇到使用按文件url来分析文件----------多表连接的DistributedCache方式,看不懂使用extends Configured i ...

  2. Codeforces 723D. Lakes in Berland

    解题思路: 1.dfs所有的水,顺便计数大小并判断是不是湖. 2.如果是湖,将大小和坐标存下来. 3.对湖按大小从小到大排序. 4.dfs前(湖的数量-k)个湖,用*填充这些湖. 代码: #inclu ...

  3. 优动漫PAINT基础系列之图层模式

    在绘画软件优动漫PAINT中,笔刷工具属性中的消除锯齿变成灰色无法选择了?铅笔绘制没有压感?快来改改图层模式~ 优动漫PAINT下载:http://www.dongmansoft.com/xiazai ...

  4. Git常见问题 资料汇总

    来源https://blog.csdn.net/albb_/article/details/80420468

  5. Springboot+swagger2的接口文档开发

    一.创建一个SpringBoot项目 1. 2. 3. 4. 把web里的web选中,SQL里选择自己需要的,点击next 二.创建各项所需的controller,configure等 1. 项目布局 ...

  6. thinkphp5 编辑时 唯一验证 解决办法

    若定义了相关的验证规则,如: namespace app\seller\validate; use think\Validate; class Goodsmtag extends Validate { ...

  7. js img图片加载失败,重新加载+断网检查

    我们常常会遇到img加载图片的时候因为网络问题或者图片过大导致图片加载失败的问题,页面就因为这张蹦掉的图变得不美观.所以我们需要图片加载失败的时候重新加载图片,前端图片加载优化 //js方法定义 fu ...

  8. Mock+Proxy在SDK项目的自己主动化測试实战

    项目背景 广告SDK项目是为应用程序APP开发者提供移动广告平台接入的API程序集合,其形态就是一个植入宿主APP的jar包.提供的功能主要有以下几点: - 为APP请求广告内容 - 用户行为打点 - ...

  9. 4.有关日期格式属性改动常识,v$nls_parameters,between and,查询指定部门的员工信息,in和null,like模糊查询,order by后面能够跟:列名、表达式、别名、序号

     1 有关日期格式属性改动常识 NLS_DATE_FORMAT           DD-MON-RR select sysdate from dual; NLS_CURRENCY         ...

  10. 《鸟哥的Linux私房菜-基础学习篇(第三版)》(三)

    第2章 Linxu怎样学习         1. Linux当前的应用角色 当前的Linux常见的应用可略分为企业应用和个人应用双方面. 首先谈了企业环境的利用. 1)网络server. 2)关键任务 ...