微信小程序 微信支付 + Java后台接口

微信小程序 微信支付 + Java后台接口

这块的内容比较复杂。在网上找了很多的文章,发现很多都不是能在我做的这个项目中跑起来。最终借助公司大佬的力量才勉强的把这块的内容完成。实属不易。
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_10&index=1
上面的链接是微信小程序开发文档关于微信支付的内容。建议看3遍以上

在微信支付之前必须要有下面5样材料

小程序的appid,APPsecret,支付商户号(mch_id),商户密钥(key),付款用户的openid
申请接入微信商户地址:https://pay.weixin.qq.com/static/applyment_guide/applyment_detail_miniapp.shtml

接下来就要贴代码了,首先是小程序端的代码:

//支付方法
    purchaseMember: function purchaseMember() {
        wx.showLoading({ title: '正在加载', mask: true });
        var that = this;
        var index = that.data.currentIndex;
        var priceInfo = that.data.priceObj;
        _utils2.default.requestPayment({
            url: '/webapi/pay/wxPay.json',
            data: { priceid: priceInfo[index].id },
            fail: function fail(res) {
                wx.showToast({ title: '支付取消', icon: 'none' });
            },
            success: function success(res) {
                wx.showToast({ title: '支付成功' });
                that.setData({ showGetMemberPopup: false });
                // 查询支付结果,支付成功后刷新用户缓存
                that.orderQuery();
            },
            callback: function callback(resultData) {
                wx.hideLoading();
                // that.data.orderno = resultData.orderno
                that.data.orderno = resultData.orderno;
            }
        });
    },
   	 orderQuery: function orderQuery() {
        wx.showLoading({ title: '正在加载', mask: true });
        var that = this;
        getApp().GET({ url: "/webapi/pay/orderQuery.json",
            data: { orderno: that.data.orderno },
            success: function success(res) {
                wx.hideLoading();
                if (res.success && res.data.state == 'SUCCESS') {
                    that.refresh();
                } else {
                    wx.showToast({ title: res.msg, icon: 'none' });
                }
            }
        });
    },

统一下单的地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
这里面的参数很重要,要好好比对,必要的参数一定要有
微信小程序 微信支付 + Java后台接口_第1张图片
微信小程序 微信支付 + Java后台接口_第2张图片
微信小程序 微信支付 + Java后台接口_第3张图片
Java后台代码相当多:
1.首先是支付的代码:
在刚支付的时候我们就要在会员权益表中增加这一条数据了,不管是否支付成功,因为支付失败那是回调之后的失败。

/**
	 * 微信内调起支付
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/wxPay", method = { RequestMethod.GET, RequestMethod.POST })
	@ResponseBody
	public Response wxPay(HttpServletRequest request) {
		// 根据请求中的token来获取缓存中的用户信息
		Response resp = new Response<>();
		Member loginUser = MemberManager.getMember(request);
		if (loginUser == null) {
			resp.setCode(CommonReturnCode.ERROR.code());
			return resp;
		}
		//前台传过来的数据
		String priceid = ServletRequestUtils.getStringParameter(request, "priceid", null);
		String latitude = ServletRequestUtils.getStringParameter(request, "payLatitude", null);
		String longitude = ServletRequestUtils.getStringParameter(request, "payLongitude", null);
		Validator validator = new Validator();
		// 获取地址情况 地址错误时不保存地址
		validator.required(latitude, "位置获取失败");
		validator.required(longitude, "位置获取失败");
		validator.number(request, "latitude", "位置获取失败");
		validator.number(request, "longitude", "位置获取失败");
		ReverseGeocodingResult RGResult = null;
		if (!validator.isError()) {
			RGResult = BaiduMapApi.getReverseGeocoding(latitude, longitude);
		}
		MemberPrice memberprice = memberPriceService.selectById(priceid);
		// 判断订单是否存在
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		String orderNum = "HYQY" + sdf.format(new Date()) + StringRandom.getRandomNum();
		BigDecimal amount = memberprice.getPrice();
		//把值塞进会员购买会员的表中
		MembershipBuyOrder order = new MembershipBuyOrder();
		order.setMemberid(loginUser.getId());
		order.setPriceid(priceid);
		order.setPricename(memberprice.getName());
		order.setDuration(memberprice.getDuration());
		order.setTimeunit(Integer.valueOf(memberprice.getTimeunit()));
		order.setAmount(amount);
		order.setPaytype(OrderEnums.PayType.MONEY.getValue());
		order.setOrderno(orderNum);
		order.setStatus(1);
		order.setCreatetime(DateUtils.dateTimeToString(new Date()));
		
		PaymentLocation plRecord = null;
		if (RGResult != null) {
			plRecord = new PaymentLocation(PaymentLocation.BusinessType.MEMBERSHIP, order.getId(),
					RGResult.getFormatted_address(), RGResult.getSematic_description(), RGResult.getAddressComponent(),
					RGResult.getLocation());
		}
		//这些必要的数据是我们表中的数据
		String appid = ApplicationConfigurer.getStringProperty("wxMiniprogramAppID", "");
		String mch_id = ApplicationConfigurer.getStringProperty("wxMiniprogramAppMchId", "");
		String webContext = ApplicationConfigurer.getStringProperty("web.context", "");
		String paternerKey = ApplicationConfigurer.getStringProperty("wxpayAppKey", "");
		try {
			// 组织支付参数信息
			Map paraMap = new HashMap();
			// 获取请求ip地址
			String ip = RequestUtil.getRequestIP(request);
			// 下单成功的回调(很重要)
			String notifyUrl = webContext + "/wxpay/callOrder/memberCallback.json";
			WXPay wxpay = new WXPay(WXMPPayConfigImpl.getInstance(), notifyUrl, true, false);
			// 拼接统一下单地址参数
			paraMap.put("openid", loginUser.getXcx_openid());
			paraMap.put("out_trade_no", orderNum);// 商品的订单号每次要唯一
			paraMap.put("fee_type", "CNY");
			// 化元为分,化小为整
			paraMap.put("total_fee", String.valueOf(amount.multiply(new BigDecimal(100)).longValue()));
			paraMap.put("mch_id", mch_id);
			paraMap.put("spbill_create_ip", ip);
			// 此路径是微信服务器调用支付结果通知路径
			paraMap.put("trade_type", "JSAPI");
			paraMap.put("body", "会员权益购买会员");
			paraMap.put("notify_url", notifyUrl);
			// 使用 wxpayAppKey 请求体 生成签名
			Map resultMap = wxpay.unifiedOrder(paraMap);

			// 发送post请求"统一下单接口"返回预支付id:prepay_id
			if (!WXPayConstants.SUCCESS.equals(resultMap.get("result_code"))) {
				return new Response<>(CommonReturnCode.ERROR, "获取失败,请稍后重试");
			}
			String prepay_id = resultMap.get("prepay_id");// 预支付id
			Map payMap = new HashMap();
			payMap.put("appId", 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, paternerKey, SignType.HMACSHA256);
			payMap.put("paySign", paySign);
			boolean result = membershipBuyOrderService.insert(order);
			Map responseResultMap = new HashMap<>();
			payMap.remove("appId");
			responseResultMap.put("payData", payMap);
			responseResultMap.put("orderno", order.getOrderno());
			if (result) {
				if (plRecord != null) {
					plRecord.setRecordid(order.getId());
					// 保证订单支付地址的唯一性
					Wrapper plWrapper = new EntityWrapper<>();
					plWrapper.eq("recordid", plRecord.getRecordid()).eq("businesstype", plRecord.getBusinesstype());
					paymentLocationService.delete(plWrapper);
					paymentLocationService.insert(plRecord);
				}
				return new Response<>(responseResultMap);
			} else {
				return new Response<>(CommonReturnCode.ERROR, "购买会员失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new Response<>(CommonReturnCode.ERROR, "购买会员失败");
	}
/**
	 * 向指定 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;
	}
/**
	 * 微信支付账单查询:该接口不做复杂的业务处理,仅根据商户订单号查询订单情况返回支付结果
	 * 
	 * @param request
	 * @param response
	 */
	@RequestMapping(value = "/orderQuery", method = { RequestMethod.POST, RequestMethod.GET })
	@ResponseBody
	public Response orderQuery(HttpServletRequest request, HttpServletResponse response) {
		String orderno = ServletRequestUtils.getStringParameter(request, "orderno", "");
		if (StringUtils.isBlank(orderno)) {
			return new Response<>(CommonReturnCode.ERROR, "订单查询失败");
		}
		try {
			WXPay wxpay = new WXPay(WXMPPayConfigImpl.getInstance());
			Map data = new HashMap();
			data.put("out_trade_no", orderno);
			Map resp = wxpay.orderQuery(data);
			if (WXPayConstants.SUCCESS.equals(resp.get("result_code"))
					&& WXPayConstants.SUCCESS.equals(resp.get("return_code"))) {
				Map resultMap = new HashMap();
				resultMap.put("state", resp.get("trade_state"));
				resultMap.put("desc", resp.get("trade_state_desc"));
				return new Response<>(resultMap);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new Response<>(CommonReturnCode.ERROR, "订单支付失败");
	}

2.支付回调的方法(很重要)

/**
	 * 购买会员积分回调
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "memberCallback", method = { RequestMethod.GET, RequestMethod.POST })
	@ResponseBody
	public void memberCallback(HttpServletRequest request, HttpServletResponse response) {
		BufferedReader br = null;
		String xml = "";
		try {
			StringBuilder result = new StringBuilder();
			br = request.getReader();
			for (String line; (line = br.readLine()) != null;) {
				if (result.length() > 0) {
					result.append("\n");
				}
				result.append(line);
			}
			String notifyData = result.toString(); // 支付结果通知的xml格式数据
			WXPay wxpay = new WXPay(WXMPPayConfigImpl.getInstance());
			Map notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
			if (wxpay.isResponseSignatureValid(notifyMap)) {
				// 签名正确,处理
				// 进行处理
				BigDecimal cash_fee = new BigDecimal(notifyMap.get("cash_fee"));
				// 根据订单流水号查询会员升级订单
				Wrapper wrapper = new EntityWrapper<>();
				wrapper.eq("orderno", notifyMap.get("out_trade_no"));
				MembershipBuyOrder record = membershipBuyOrderService.selectOne(wrapper);

				// 比对支付金额是否正确和支付状态
				if (cash_fee.compareTo(record.getAmount().multiply(new BigDecimal(100))) == 0
						&& record.getStatus() == OrderEnums.Status.TODO.getValue()) {
					Member member = memberService.selectById(record.getMemberid());
					//处理复杂的各种表的逻辑
					if (flag) {
						xml = "";
					}
				}
			} else {
				// 签名错误,如果数据里没有sign字段,也认为是签名错误
			}
			response.getWriter().write(xml);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

再调用的话就可以了 总结就是回调的方法真的非常重要!!!
微信小程序 微信支付 + Java后台接口_第4张图片

你可能感兴趣的:(微信小程序,微信小程序,微信支付,Java后台,支付的回调方法)