微信小程序调用JSAPI进行微信支付

微信小程序调用JSAPI进行微信支付

1、小程序中先调用接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易后调起支付;
2、商户server调用再次签名;
3、唤起微信支付页面,进行支付;
4、支付成功后,调用回调接口,进行微信支付通知;
//调用微信登录,获取openid,同时生成订单编号,支付金额;
goLoginGetOpenId:function(){
	var t = this;
	//登录获取临时凭证  code
	uni.login({
		provider: 'weixin',
		success: function(res) {
			if (res.code) {
				console.log("res.code: ",res.code);
				//发起网络请求  获取 openid 和 session_key
				util.post(
					t.mainUrl + '/xieHuiZhuCe/getOpenId',
					{
						code:res.code,
						recordId:t.id
					},
					function(result) {
						console.log("xieHuiZhuCe/getOpenId",JSON.stringify(result));
						t.openid = result.data.openid;
						 /* 会员类别
						 * 普通会员 1.普通会员:500元/届;
						 * 高级会员 2.高级会员:500元/届;
						 * 资深会员 3.资深会员:免收会费;
						 * 学生会员 4.学生会员:免收会费,一次性收取注册费50元;
						 */
						t.hylb = result.data.hylb;
						if(t.hylb == 1|| t.hylb == 2){
							// t.payMoney = 500;
							t.payMoney = 0.01;
						}else if(t.hylb == 4){
							// t.payMoney = 50;
							t.payMoney = 0.01;
						}
						//商户订单号
						t.out_trade_no = result.data.out_trade_no;
					}
				);
			}
		}
	})
}
//生成预支付交易单
getPrePayId(){
	var t = this;
	util.post(
		t.mainUrl + '/xieHuiZhuCe/getPrePayId',
		{
			out_trade_no : t.out_trade_no,
			hylb : t.hylb,
			openid : t.openid,
			payMoney :t.payMoney
		},
		function(result) {
			if(result.status == '0001'){
				console.log("getPrePayId: ",result.prepay_id);
				t.prepay_id = result.prepay_id;
				if(!result.prepay_id){
					uni.showToast({
						icon: 'none',
						mask:true,
						duration:2000,
						title: '该订单已支付,请勿重复支付!'
					});
					return;
				}
				//商户server调用再次签名
				t.WxSecondSign();
			}else{
				uni.showToast({
					title: '服务器忙  请稍后再试'
				});
			}
		}
	);
}
//调用微信商户服务进行二次签名后,发起支付
WxSecondSign(){
	var t = this;
	util.post(
		t.mainUrl + '/xieHuiZhuCe/WxSecondSign',
		{
			prepay_id : t.prepay_id
		},
		function(result) {
			if(result.status == '0001'){
				uni.requestPayment({
					provider: 'wxpay',
					timeStamp: result.timeStamp+'',
					nonceStr: result.nonce_str,
					package: 'prepay_id='+t.prepay_id,
					signType: 'MD5',
					paySign: result.paySign,
					success: function (res) {
						console.log(res);//res.errMsg == "requestPayment:ok"
						console.log('success:' + JSON.stringify(res));
						uni.navigateTo({
							url:'./index'
						})
					},
					fail: function (err) {
						console.log('fail:' + JSON.stringify(err));
					},
					complete(err){
						 console.log('complete:' + JSON.stringify(err));
					}
				});
			}else{
				uni.showToast({
					title: '服务器忙  请稍后再试'
				});
			}
		}
	);
}
/**
 * 小程序获取微信信息
 * @param paramMap
 * @return
 */
@RequestMapping("/getOpenId")
@ResponseBody
public Map getOpenId(@RequestBody Map paramMap) {
	Map resultMap = new HashMap();
	//获取openid
	String result = HttpClient4.doGet("https://api.weixin.qq.com/sns/jscode2session?appid="+appID+"&secret="+appSecret+"&js_code="+paramMap.get("code")+"&grant_type=authorization_code");
	Gson gson = new Gson();
	Map map=gson.fromJson(result, HashMap.class);
	//查询会员信息
	int recordId = StringUtils.getIntegerByObj(paramMap.get("recordId"));
	if(recordId!=0){
		XieHui_Record xieHuiRecord = xieHuiRecordRepository.getOne(recordId);
		//生成订单信息
		List<XieHui_Order> orderList = xieHuiOrderRepository.findOrderByXiehui_record_idAndIsdel(StringUtils.getStringByObj(paramMap.get("recordId")));
		XieHui_Order order = new XieHui_Order();
		if(orderList == null || orderList.size() == 0){
			order.setXiehui_record_id(StringUtils.getStringByObj(paramMap.get("recordId")));
			int randomNum = (int) (Math.random() * 1999 + 5000);
			String out_trade_no = TimeUtils.getNowFormatTimeStringyyyyMMddHHmmssSSS() + randomNum;
			order.setOrder_number(out_trade_no);
			xieHuiOrderRepository.save(order);
		}else{
			order = orderList.get(0);
		}
		//商户订单号
		map.put("out_trade_no",order.getOrder_number());
		/**
		 * 会员类别
		 * 普通会员 1.普通会员:500元/届;
		 * 高级会员 2.高级会员:500元/届;
		 * 资深会员 3.资深会员:免收会费;
		 * 学生会员 4.学生会员:免收会费,一次性收取注册费50元;
		 */
		map.put("hylb",xieHuiRecord.getHylb());
	}
	resultMap.put("data", map);
	resultMap.put("status", ConstantUtil.status_success);
	resultMap.put("msg", "请求成功");
	return resultMap;
}
/**
 * 商户在小程序中先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易后调起支付。
 * 参数校验地址: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
 * @return Map
 */
@RequestMapping("getPrePayId")
@ResponseBody
public Map getPrePayId(@RequestBody Map param) {
	Map resultMap = new HashMap();
	//商户号
	String mch_id = "1896584523";
	//随机数
	String nonce_str = WechatUtil.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());
	//商品描述	body【商家名称-销售商品类目】【腾讯-游戏】【线上电商,商家名称必须为实际销售商品的商家】
	String subject = "针灸学会-知识";//前端上送的支付描述
	//商户订单号  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
	String out_trade_no = StringUtils.getStringByObj(param.get("out_trade_no"));
	//标价金额	total_fee   金额转化为分为单位 微信支付以分为单
	String total_amount = StringUtils.getStringByObj(param.get("payMoney"));//支付金额500
	/**
	 * 会员类别
	 * 普通会员 1.普通会员:500元/届;
	 * 高级会员 2.高级会员:500元/届;
	 * 资深会员 3.资深会员:免收会费;
	 * 学生会员 4.学生会员:免收会费,一次性收取注册费50元;
	 */
	int hylb = StringUtils.getIntegerByObj(param.get("hylb"));
	if(hylb == 4){
		total_amount = StringUtils.getStringByObj(param.get("payMoney"));//支付金额50
	}
	String finalmoney = WechatUtil.getMoney(total_amount);
	//终端IP	spbill_create_ip 【支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP】 服务器ip地址
	String spbill_create_ip = "127.0.0.1";
	System.out.println("spbill_create_ip=" + spbill_create_ip);
	//通知地址【异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。】
//  String notify_url = "http://61.185.224.91:16780/zhengJian/xieHuiZhuCe/wxPayCallBack";
	String notify_url = config.getNotify_url();
	//交易类型【JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付】
	String tradeType = "JSAPI";
	//用户标识【trade_type=JSAPI,此参数必传】
	String openid = StringUtils.getStringByObj(param.get("openid"));

	//签名数据
	Map<String, String> reqData = new HashMap();
	reqData.put("appid", appID);
	reqData.put("mch_id", mch_id);
	reqData.put("nonce_str", nonce_str);
	reqData.put("sign_type", MD5);
	reqData.put("body", subject);
	reqData.put("out_trade_no", out_trade_no);
	reqData.put("total_fee", finalmoney);
	reqData.put("spbill_create_ip", spbill_create_ip);
	reqData.put("notify_url", notify_url);
	reqData.put("trade_type", tradeType);
	reqData.put("openid", openid);

	//签名MD5加密
	String sign = "";
	try {
		logger.info("签名数据:" + reqData);
		System.out.println("reqData=" + reqData);
		sign = WechatUtil.generateSignature(reqData, Key);//Key   商户号密钥
		reqData.put("sign", sign);
	} catch (Exception e) {
		logger.error("微信签名数据:" + e);
		return resultMap;

	}
	logger.info("签名数据:" + sign);
	//封装xml报文
	String xml = WechatUtil.parseXML(reqData);
	System.out.println("xml:"+xml);
	String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信统一下单接口
	String prepay_id = "";
	Map map = new HashMap();
	try {
		//预下单 获取接口地址
		map = WechatUtil.getMwebUrl(createOrderURL, xml);
		String return_code = (String) map.get("return_code");
		String return_msg = (String) map.get("return_msg");
		if ("SUCCESS".equals(return_code) && "OK".equals(return_msg)) {
			//预支付交易会话标识【微信生成的预支付会话标识,用于后续接口调用中使用,该值有效期为2小时】
			prepay_id = (String) map.get("prepay_id");
			logger.info("map=" + map);
			resultMap.put("prepay_id", prepay_id);
			resultMap.put("status", ConstantUtil.status_success);
			resultMap.put("msg", "请求成功");
		} else {
			logger.error("统一支付接口获取预支付订单出错" + map);
			resultMap.put("msg", "支付错误");
			return resultMap;
		}
	} catch (Exception e) {
		logger.error("统一支付接口获取预支付订单出错" + e);
		resultMap.put("msg", "支付错误");
		return resultMap;
	}
	return resultMap;
}
/**
 * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
 * @param data 待签名数据
 * @param key  API密钥
 * @return 签名
 */
public static String generateSignature(final Map<String, String> data, String key) throws Exception {
	Set<String> keySet = data.keySet();
	String[] keyArray = keySet.toArray(new String[keySet.size()]);
	Arrays.sort(keyArray);
	StringBuilder sb = new StringBuilder();
	for (String k : keyArray) {
		if (data.get(k).trim().length() > 0) {// 参数值为空,则不参与签名
			sb.append(k).append("=").append(data.get(k).trim()).append("&");
		}
	}
	sb.append("key=").append(key);
	try {
		return MD5(sb.toString()).toUpperCase();
	} catch (Exception e) {
		throw new Exception();
	}
}
/**
 * 参数组装为xml
 * @param parameters
 * @return
 */
public static String parseXML(Map<String, String> parameters) {
	StringBuffer sb = new StringBuffer();
	sb.append("<xml>");
	Set es = parameters.entrySet();
	Iterator it = es.iterator();
	while (it.hasNext()) {
		Map.Entry entry = (Map.Entry) it.next();
		String k = (String) entry.getKey();
		String v = (String) entry.getValue();
		if (null != v && !"".equals(v) && !"appkey".equals(k)) {
			sb.append("<" + k + ">" + parameters.get(k) + "</" + k + ">\n");
		}
	}
	sb.append("</xml>");
	return sb.toString();
}
/**
 * 发送请求,解析返回的xml
 * @param url
 * @param xmlParam
 * @return
 */
public static Map getMwebUrl(String url, String xmlParam) {
	String jsonStr = null;
	HttpClient httpClient = new HttpClient();
	Map map = new HashMap();
	try {
		PostMethod method = null;
		RequestEntity reqEntity = new StringRequestEntity(xmlParam, "text/json", "UTF-8");
		method = new PostMethod(url);
		method.setRequestEntity(reqEntity);
		method.addRequestHeader("Content-Type", "application/json;charset=utf-8");
		httpClient.executeMethod(method);
		StringBuffer resBodyBuf = new StringBuffer();
		byte[] responseBody = new byte[1024];
		int readCount = 0;
		BufferedInputStream is = new BufferedInputStream(method.getResponseBodyAsStream());
		while ((readCount = is.read(responseBody, 0, responseBody.length)) != -1) {
			resBodyBuf.append(new String(responseBody, 0, readCount, "utf-8"));
		}
		jsonStr = resBodyBuf.toString();
		System.out.println(jsonStr);
		map = parseXmlToList(jsonStr);
	} catch (Exception e) {
		e.printStackTrace();
	}
	return map;
}
/**
 * 商户server调用再次签名
 * @param request
 * @return
 */
@RequestMapping("/WxSecondSign")
@ResponseBody
public Map WxSecondSign(HttpServletRequest request,@RequestBody Map paramMap) {
	Map resultMap = new HashMap();
	try {
		String prepay_id = StringUtils.getStringByObj(paramMap.get("prepay_id"));
		//随机数
		String nonce_str = WechatUtil.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());
		Long timeStamp = System.currentTimeMillis()/1000;
		//签名数据
		StringBuffer signData = new StringBuffer();
		signData.append("appId="+appID+"&");
		signData.append("nonceStr="+nonce_str+"&");
		signData.append("package=prepay_id="+prepay_id+"&");
		signData.append("signType="+MD5+"&");
		signData.append("timeStamp="+timeStamp+"&");
		signData.append("key="+Key);
		String paySign = WechatUtil.MD5(signData.toString());
		resultMap.put("nonce_str", nonce_str);
		resultMap.put("timeStamp", timeStamp);
		resultMap.put("paySign", paySign);
		resultMap.put("status", ConstantUtil.status_success);
		resultMap.put("msg", "请求成功");
	} catch (Exception e) {
		resultMap.put("status", ConstantUtil.status_error);
		resultMap.put("msg", "请求失败");
		e.printStackTrace();
	}
	return resultMap;
}
/**
 * 生成 MD5
 * @param data 待处理数据
 * @return MD5结果
 */
public static String MD5(String data) throws Exception {
	java.security.MessageDigest md = MessageDigest.getInstance("MD5");
	byte[] array = md.digest(data.getBytes("UTF-8"));
	StringBuilder sb = new StringBuilder();
	for (byte item : array) {
		sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
	}
	return sb.toString().toUpperCase();
}
/**
 * 微信支付通知
 * @param request
 * @param response
 * @throws Exception
 */
@RequestMapping(value = "/wxPayCallBack")
public void weixinPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
	BufferedReader reader = request.getReader();
	String line = "";
	Map map = new HashMap();
	String xml = "<xml><return_code><![CDATA[FAIL]]></xml>";
	StringBuffer inputString = new StringBuffer();
	while ((line = reader.readLine()) != null) {
		inputString.append(line);
	}
	request.getReader().close();
	logger.info("----接收到的报文---" + inputString.toString());
	if (inputString.toString().length() > 0) {
		map = WechatUtil.parseXmlToList(inputString.toString());
	} else {
		logger.info("接受微信报文为空");
	}
	logger.info("map=" + map);
	if (map != null && "SUCCESS".equals(map.get("result_code"))) {
		//成功的业务。。。
		this.updateOrderStatus(map);
		xml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
		logger.info("商户订单号: 【" + map.get("out_trade_no") + "】支付成功");
	} else {
		//失败的业务。。。
		logger.error("商户订单号: 【" + map.get("out_trade_no") + "】支付失败,  "+"描述:【errCode:"+map.get("err_code")+", errCodeDes:"+map.get("err_code_des")+"】");
	}
	//告诉微信端已经确认支付成功
	response.getWriter().write(xml);
}
/**
 * description: 解析微信通知xml
 * @param xml
 * @return
 * @see
 */
@SuppressWarnings({"unused", "rawtypes", "unchecked"})
public static Map parseXmlToList(String xml) {
	Map retMap = new HashMap();
	try {
		StringReader read = new StringReader(xml);
		// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
		InputSource source = new InputSource(read);
		// 创建一个新的SAXBuilder
		SAXBuilder sb = new SAXBuilder();
		// 通过输入源构造一个Document
		Document doc = (Document) sb.build(source);
		Element root = doc.getRootElement();// 指向根节点
		List<Element> es = root.getChildren();
		if (es != null && es.size() != 0) {
			for (Element element : es) {
				retMap.put(element.getName(), element.getValue());
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
	return retMap;
}
/**
 * 元转换成分
 * @param amount
 * @return
 */
public static String getMoney(String amount) {
	if (amount == null) {
		return "";
	}
	// 金额转化为分为单位
	String currency = amount.replaceAll("\\$|\\¥|\\,", "");  //处理包含, ¥ 或者$的金额
	int index = currency.indexOf(".");
	int length = currency.length();
	Long amLong = 0l;
	if (index == -1) {
		amLong = Long.valueOf(currency + "00");
	} else if (length - index >= 3) {
		amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
	} else if (length - index == 2) {
		amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
	} else {
		amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
	}
	return amLong.toString();
}
/**
 * 生成随机数
 * @param buffer
 * @return
 */
public final static String getMessageDigest(byte[] buffer) {
	char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	try {
		MessageDigest mdTemp = MessageDigest.getInstance("MD5");
		mdTemp.update(buffer);
		byte[] md = mdTemp.digest();
		int j = md.length;
		char str[] = new char[j * 2];
		int k = 0;
		for (int i = 0; i < j; i++) {
			byte byte0 = md[i];
			str[k++] = hexDigits[byte0 >>> 4 & 0xf];
			str[k++] = hexDigits[byte0 & 0xf];
		}
		return new String(str);
	} catch (Exception e) {
		return null;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值