微信小程序支付案例

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/q438944209/article/details/82797520

小程序支付说明

此案例用作小程序缴费的情况。过程为:先触发微信小程序支付后台得到预付款ID(prepare_id),然后小程序前台会自动弹出一个对应金额的支付窗口,然后用户输入正确密码,支付成功,触发用户的回调函数做业务操作。

 

更多分布式微服务课程关注:www.majiaxueyuan.com

 

得到微信的code。小程序和公众号都可以直接得到

AccessToken获取方法(顺便写的)

Body<String> getAccessToken(String code) {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + WxPayConfig.APP_ID + "&secret="
				+ WxPayConfig.APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
		// 创建一个GET对象
		try {
			HttpGet get = new HttpGet(url);
			// 执行请求
			CloseableHttpResponse response = httpClient.execute(get);
			HttpEntity entity = response.getEntity();
			String string = EntityUtils.toString(entity, "utf-8");
			System.out.println(string);
			return new Body<String>().setSuccess(string);
		} catch (Exception e) {
			return new Body<String>().setError("登录异常");
		}
	}

微信支付配置文件

public class WxPayConfig {
	// 小程序appid
	public static final String APP_ID = "";
	// APP——Secret
	public static final String APP_SECRET = "";
	// 微信支付的商户号
	public static final String MCH_ID = "";
	// 微信支付的商户秘钥
	public static final String KEY = "";
	// 支付成功后的服务器回调url
	public static final String notify_url = "";
	// 签名方式,固定值
	public static final String SIGNTYPE = "MD5";
	// 交易类型,小程序支付的固定值为JSAPI
	public static final String TRADETYPE = "JSAPI";
	// 微信统一下单接口地址
	public static final String pay_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	// 微信直接转账到个人请求
	public static final String transfor_url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";

	public static final String STATIC_NUM = "a0A0b1B2c1C3d2D1e3E2f4F3g5G7h4H6i5Ij4J9k5K6l6Lm7M7n8N8o9Op0PqQrRsStTuUv9VwWxXy8YzZ";
}

 

预付款ID

微信支付分为两步,第一步可以理解为获得一个预付款ID

/**
	 * 微信支付获取预付款信息返回给小程序唤起支付界面
	 * @param unique:系统订单号
	 * @param openId:用户唯一OpenId
	 * @param totleMoney:付款金额,字符串(单位:分)
	 * @param ipAddr:IP地址
	 * @return
	 */
	public Body<String> wxPay(String unique, String openId, String totleMoney, String ipAddr) {
		// 付款金额
		try {
			// 生成的随机字符串
			String nonce_str = getRandomStringByLength(32);
			// 获取客户端的ip地址
			String spbill_create_ip = ipAddr;
			// 商品名称
			String body = "码家学院永久会员会员充值";
			// 组装参数,用户生成统一下单接口的签名
			Map<String, String> packageParams = new HashMap<String, String>();
			packageParams.put("appid", WxPayConfig.APP_ID);
			packageParams.put("body", body);
			packageParams.put("mch_id", WxPayConfig.MCH_ID);
			packageParams.put("nonce_str", nonce_str);
			packageParams.put("notify_url", WxPayConfig.notify_url);// 支付成功后的回调地址
			packageParams.put("openid", openId);
			packageParams.put("out_trade_no", unique);// 商户订单号
			packageParams.put("spbill_create_ip", spbill_create_ip);
			packageParams.put("total_fee", totleMoney); // 支付金额,这边需要转成字符串类型,否则后面的签名会失败
			packageParams.put("trade_type", WxPayConfig.TRADETYPE);// 支付方式

			String prestr = PayUtil.createLinkString(packageParams); //
			// MD5运算生成签名,这里是第一次签名,用于调用统一下单接口
			String mysign = PayUtil.sign(prestr, WxPayConfig.KEY, "utf-8").toUpperCase();

			// 拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去
			String xml = "<xml>" + "<appid>" + WxPayConfig.APP_ID + "</appid>" + "<body><![CDATA[" + body + "]]></body>"
					+ "<mch_id>" + WxPayConfig.MCH_ID + "</mch_id>" + "<nonce_str>" + nonce_str + "</nonce_str>"
					+ "<notify_url>" + WxPayConfig.notify_url + "</notify_url>" + "<openid>" + openId + "</openid>"
					+ "<out_trade_no>" + unique + "</out_trade_no>" + "<spbill_create_ip>" + spbill_create_ip
					+ "</spbill_create_ip>" + "<total_fee>" + totleMoney + "</total_fee>" + "<trade_type>"
					+ WxPayConfig.TRADETYPE + "</trade_type>" + "<sign>" + mysign + "</sign>" + "</xml>";

			System.out.println("调试模式_统一下单接口 请求XML数据:" + xml);

			// 调用统一下单接口,并接受返回的结果
			String result = PayUtil.httpRequest(WxPayConfig.pay_url, "POST", xml);

			System.out.println("调试模式_统一下单接口 返回XML数据:" + result);

			// 将解析结果存储在HashMap中
			Map map = PayUtil.doXMLParse(result);

			// 返回状态码
			String return_code = (String) map.get("return_code");

			// 返回给小程序端需要的参数
			Map<String, Object> response = new HashMap<String, Object>();
			if (return_code == "SUCCESS" || return_code.equals(return_code)) {
				// 返回的预付单信息
				String prepay_id = (String) map.get("prepay_id");
				response.put("nonceStr", nonce_str);
				response.put("package", "prepay_id=" + prepay_id);
				Long timeStamp = System.currentTimeMillis() / 1000;
				response.put("timeStamp", timeStamp + "");// 这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
				// 拼接签名需要的参数
				String stringSignTemp = "appId=" + WxPayConfig.APP_ID + "&nonceStr=" + nonce_str + "&package=prepay_id="
						+ prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
				// 再次签名,这个签名用于小程序端调用wx.requesetPayment方法
				String paySign = PayUtil.sign(stringSignTemp, WxPayConfig.KEY, "utf-8").toUpperCase();
				response.put("paySign", paySign);
			}
			response.put("appid", WxPayConfig.APP_ID);
			String json = JSON.toJSONString(response);
			return new Body<String>().setSuccess(json);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

 

随机字符串生成方法

public static String getRandomStringByLength(int length) {
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
}

异步回调函数

(用户处理我们自己系统中的逻辑)

public void wxNotify(HttpServletRequest request, HttpServletResponse response) {
		try {
			BufferedReader br = new BufferedReader(
					new InputStreamReader((ServletInputStream) request.getInputStream()));
			String line = null;
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
			br.close();
			// sb为微信返回的xml
			String notityXml = sb.toString();
			String resXml = "";
			System.out.println("接收到的报文:" + notityXml);
			Map map = PayUtil.doXMLParse(notityXml);
			String returnCode = (String) map.get("return_code");
			if ("SUCCESS".equals(returnCode)) {
				// 支付成功,需要根据订单号来判断此订单号在系统中是否已经被处理过了
				// 这就是所说的幂等性的处理,避免我们的订单被交易多次
				// 处理完成过后告诉微信处理成功,避免微信触发重试机制
				map.get("result_code");
				map.get("transaction_id");
				// 告诉微信处理完成
				resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
						+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
			} else {
				// 告诉微信处理失败
				resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
						+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
			}
			System.out.println("微信支付回调数据结束");
			BufferedOutputStream out;
			out = new BufferedOutputStream(response.getOutputStream());
			out.write(resXml.getBytes());
			out.flush();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

到这里小程序当中的微信支付就完成了,也是很简答的

展开阅读全文

没有更多推荐了,返回首页