最详细的微信支付JSAPI完整流程_java版本

要实现微信支付要满足几个条件:
一、有一个服务号,菜单栏里面有微信支付菜单的公众号
最详细的微信支付JSAPI完整流程_java版本_第1张图片

二、需要开通商户号,不是公众号,必须和公众号做关联操作
在这里插入图片描述

常用的几个参数 下面例子参数值已经经过处理

public final class WxConfig {
	public final static String appId = "wx98dc29047cexxxx"; // 公众号appid
	public final static String mchId = "1566911111";// 商户ID
	public final static String key = "xxxxxxx4TI4srY33SwkyXYojBzK6Fsp"; // 商户KEY 跟微信支付约定的密钥 
	public final static String payUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 统一下单地址
	public final static String tradeType = "JSAPI"; // 支付方式
	public final static String secret="xxx9b86bdb6637a4ccfaf6e7e2609";//商户APPSECRET
}

以下是微信支付流程,后面会根据流程上响应的代码
最详细的微信支付JSAPI完整流程_java版本_第2张图片
微信工具包下载,其中很多类可以使用

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
最详细的微信支付JSAPI完整流程_java版本_第3张图片

1、获取用户code

https://open.weixin.qq.com/connect/oauth2/authorize

var code = getUrlParam('code') // 截取路径中的code,如果没有就去微信授权,如果已经获取到了就直接传code给后台获取openId
var local = window.location.href
if (code == null || code === '') {
	window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx98dc29047xxxxx&redirect_uri=' + encodeURIComponent(local) +'&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect'
}

中间有几个参数
最详细的微信支付JSAPI完整流程_java版本_第4张图片
微信会通过回调的方式跳回原来的页面,code就是用户的会话ID了,某个时段有效。

redirect_uri/?code=CODE&state=STATE

2、获取openId

https://api.weixin.qq.com/sns/oauth2/access_token

拿到code以后为了安全性提交到后台,后台我这里是用的java springboot框架

String code = json.get("code").toString();
String res = get("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WxConfig.appId + "&secret="+ WxConfig.secret + "&code=" + code + "&grant_type=authorization_code");
			JSONObject json1 = JSONObject.parseObject(res);
			String openId = json1.getString("openid");
			System.out.println(openId+"------------------------------");

这里使用的 WxConfig 就是文章开头的配置文件类

public String get(String url) throws Exception {
		// 创建HttpClient实例
		CloseableHttpClient client = HttpClientBuilder.create().build();
		// 根据URL创建HttpGet实例
		HttpGet get = new HttpGet(url);
		// 执行get请求,得到返回体
		HttpResponse response = client.execute(get);
		// 判断是否正常返回
		if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
			// 解析数据
			String data = EntityUtils.toString(response.getEntity(), Charsets.UTF_8);
			System.out.println(data);
			return data;
		}
		return "";
	}
		<dependency>
			<groupId>org.apache.httpcomponentsgroupId>
			<artifactId>httpclientartifactId>
			<version>4.5.3version>
		dependency>
		<dependency>
			<groupId>com.alibabagroupId>
			<artifactId>fastjsonartifactId>
			<version>1.2.3version>
		dependency>

3、发起订单

https://api.mch.weixin.qq.com/pay/unifiedorder

拿到openId以后就可以发起订单了

@RequestMapping("/payH5")
	@ResponseBody
	public Object payH5(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, Object> json)
			throws Exception {
		try {
			String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
			//记得自己把订单id保存下来 orderNo 
			String code = json.get("code").toString();

			String res = get("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WxConfig.appId + "&secret="
					+ WxConfig.secret + "&code=" + code + "&grant_type=authorization_code");
			JSONObject json1 = JSONObject.parseObject(res);
			String openId = json1.getString("openid"); //获取的用户唯一标识
			System.out.println(openId+"------------------------------");
			Map<String, String> paraMap = new HashMap<>();
			paraMap.put("appid", WxConfig.appId);//公众号appid
			paraMap.put("body", json.get("body").toString());//商品说明
			paraMap.put("mch_id", WxConfig.mchId);//商家id
			paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
			paraMap.put("openid", openId);			
			paraMap.put("out_trade_no", orderNo);
			paraMap.put("spbill_create_ip", "120.79.1.1");
			paraMap.put("total_fee", String.valueOf((int)(Double.parseDouble(kc.getSpjg())*100)));
			paraMap.put("trade_type", WxConfig.tradeType);
			paraMap.put("notify_url","http://yunkt.zmxzc.com//api/wxnotify");
			String apiKey = WxConfig.key;
			System.out.println(WXPayUtil.mapToXml(paraMap));
			String sign = WXPayUtil.generateSignature(paraMap, apiKey);
			paraMap.put("sign", sign);
			String xml = WXPayUtil.mapToXml(paraMap);
			System.out.println(xml);
			// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
			String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

			String xmlStr = WXPayReport.httpRequest(unifiedorder_url, xml, 2000, 5000);
			// 以下内容是返回前端页面的json数据
			System.out.println(xmlStr);
			String prepay_id = "";// 预支付id
			if (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", WxConfig.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, WxConfig.key);
			payMap.put("paySign", paySign);
			payMap.put("orderNo", orderNo);
			payMap.put("success", "0");
			return payMap;

		} catch (Exception e) {
			e.printStackTrace();
			Map<String, String> payMap = new HashMap<String, String>();
			payMap.put("success", "1");
			return payMap;

		}
//        return new SuccessResponseData();
	}

httpRequest 方法改写新增了 WXPayReport工具包中 的请求方法

public static String httpRequest(String url,String data, int connectTimeoutMs, int readTimeoutMs) throws Exception{
        BasicHttpClientConnectionManager connManager;
        connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", SSLConnectionSocketFactory.getSocketFactory())
                        .build(),
                null,
                null,
                null
        );
        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", WXPayConstants.USER_AGENT);
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
    }

payMap 返回的值就是我们调用支付所需要的参数的,所有的工作就是为了获取这些

4、调用微信支付,必须在微信内置浏览器,不然会失败

WeixinJSBridge.invoke('getBrandWCPayRequest', {
								"appId": data.appId, //公众号名称,由商户传入
								"timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
								"nonceStr": data.nonceStr, //随机串
								"package": data.package,
								"signType": data.signType, //微信签名方式:
								"paySign": data.paySign //微信签名
							}, function(res) {
								console.log(res);
								//window.location.href = local
								if (res.err_msg == "get_brand_wcpay_request:ok") {
									alert('支付成功');
									window.location.href =localStorage.getItem('location');
								} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
									alert('支付取消');
									window.location.href =localStorage.getItem('location');
								} else if (res.err_msg == "get_brand_wcpay_request:fail") {
									alert('支付失败');
									window.location.href =localStorage.getItem('location');
								}else{
									alert('支付异常');	
									window.location.href =localStorage.getItem('location');
								}
							})

5、查询订单支付状态

Map<String, String> paraMap = new HashMap<>();
				paraMap.put("appid", WxConfig.appId);
				paraMap.put("mch_id", WxConfig.mchId);
				paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
				paraMap.put("out_trade_no", f.getDdid());//前面的 String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
				paraMap.put("spbill_create_ip", "120.79.1.1");
				String apiKey = WxConfig.key;
				String sign = WXPayUtil.generateSignature(paraMap, apiKey);
				paraMap.put("sign", sign);
				String xml = WXPayUtil.mapToXml(paraMap);
				System.out.println(xml);
				// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
				String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/orderquery";

				String xmlStr = WXPayReport.httpRequest(unifiedorder_url, xml, 2000, 5000);
				// 以下内容是返回前端页面的json数据
				System.out.println(xmlStr);
				
				if (xmlStr.indexOf("SUCCESS") != -1) {
					Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
					if(map.get("trade_state")!=null&&((String) map.get("trade_state")).equals("SUCCESS")){
						//修改本地订单状态
						//这里的订单就是前面的String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
					}
				}

最详细的微信支付JSAPI完整流程_java版本_第5张图片

<xml>
   <return_code>return_code>
   <return_msg>return_msg>
   <appid>appid>
   <mch_id>mch_id>
   <device_info>device_info>
   <nonce_str>nonce_str>
   <sign>sign>
   <result_code>result_code>
   <openid>openid>
   <is_subscribe>is_subscribe>
   <trade_type>trade_type>
   <bank_type>bank_type>
   <total_fee>1total_fee>
   <fee_type>fee_type>
   <transaction_id>transaction_id>
   <out_trade_no>out_trade_no>
   <attach>attach>
   <time_end>time_end>
   <trade_state>trade_state>
xml>

这里整个流程就结束了。

你可能感兴趣的:(java,前端内容,第三方API,微信支付,java支付流程,JSAPI支付开发,openid,微信商户号)