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

要实现微信支付要满足几个条件:
一、有一个服务号,菜单栏里面有微信支付菜单的公众号
在这里插入图片描述

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

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

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
}

以下是微信支付流程,后面会根据流程上响应的代码
在这里插入图片描述
微信工具包下载,其中很多类可以使用

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
在这里插入图片描述

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'
}

中间有几个参数
在这里插入图片描述
微信会通过回调的方式跳回原来的页面,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.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.3</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.3</version>
		</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("-", "");
					}
				}

在这里插入图片描述

<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <device_info><![CDATA[1000]]></device_info>
   <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>
   <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>
   <is_subscribe><![CDATA[Y]]></is_subscribe>
   <trade_type><![CDATA[MICROPAY]]></trade_type>
   <bank_type><![CDATA[CCB_DEBIT]]></bank_type>
   <total_fee>1</total_fee>
   <fee_type><![CDATA[CNY]]></fee_type>
   <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>
   <out_trade_no><![CDATA[1415757673]]></out_trade_no>
   <attach><![CDATA[订单额外描述]]></attach>
   <time_end><![CDATA[20141111170043]]></time_end>
   <trade_state><![CDATA[SUCCESS]]></trade_state>
</xml>

这里整个流程就结束了。

  • 7
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值