开发前准备
  1. 注册微信商户号:https://pay.weixin.qq.com/index.php
  2. 注册微信小程序:https://mp.weixin.qq.com/
  3. 在小程序中配置商户号,并且开通微信支付功能,如下图:
首先请仔细阅读 微信支付官方文档

抖音小程序支付功能java java小程序支付功能开发_抖音小程序支付功能java


根据文档简述其开发流程主要为:

1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】 2、商户server调用支付统一下单,api参见公共api【统一下单API】

3、商户server调用再次签名,api参见公共api【再次签名】

4、商户server接收支付通知,api参见公共api【支付结果通知API】

5、商户server查询支付结果,api参见公共api【查询订单API】

获取微信用户的openid

小程序端:

wx.login({
      success: function (r) {
        var params = {
          userId: userid,   //微信用户id,用于绑定生成的openid, 可根据业务逻辑灵活处理
          code: r.code
        }
        api.getWxOpenid(params)   //封装等微信小程序api,用于请求后台接口
        .then((res) => {
          if (res.code == 101) {
          	//获取微信用户的 openid  并存入缓存   --可根据业务逻辑灵活处理
            wx.setStorageSync('WXOPENID', res.data.WXOPENID);
          } else {
            wx.showToast({
              title: res.msg,
              icon: 'none',
              duration: 1000
            })
          }
        })
      }
    })

java后台:

APPID: 小程序的appid    SECRET: 小程序的Secret
String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+APPID+"&secret="+SECRET+"&js_code="+code+"&grant_type=authorization_code";
String result = HttpUtils.sendGet(url);
return JSONObject.parseObject(result, PageData.class);
生成统一订单
/**
	* 获取微信小程序订单支付参数
	* @param paramsPd  统一下单接口部分参数  
	* 	{
	* 		必需参数 【body: 商品简单描述, openid: 微信用户ID, outTradeNo: 商户自己的订单号码, ip: IP地	址, totalFee: 订单总金额,单位为分】
	* 		可选参数 【  detail: 商品详情,   attach: 附加数据】
	*  }
	* @param partner  商户号
	* @param partnerkey 商户号密钥
	* @return
	*/
	public static PageData getWxPayParameters(PageData paramsPd, String partner, String partnerkey) {
		PageData result = new PageData();
		Map<String, String> params = new HashMap<>();
		//必需参数
		params.put("appid", APPID);  //小程序ID
		params.put("mch_id", partner);  //商户号    ●注意
		params.put("body", paramsPd.getString("body"));  //body 商品简单描述
		params.put("nonce_str", Sha1Util.getNonceStr());   //随机字符串
		params.put("notify_url", UNIFY_NOTIFY_URL);  //异步通知的地址,支付回调接口地址
		params.put("openid", paramsPd.getString("openid"));     //openid   wx.login({})返回的
		params.put("out_trade_no", paramsPd.getString("outTradeNo"));   //商户自己的订单号码
		params.put("spbill_create_ip", paramsPd.getString("ip"));   //IP地址
		params.put("total_fee", paramsPd.getString("totalFee"));    //支付多少钱
		params.put("trade_type", "JSAPI");   //交易类型  JSAPI
		//可选参数
		if(StringUtils.isNotBlank(paramsPd.getString("detail"))) {
			params.put("detail", paramsPd.getString("detail"));   //商品详情
		}
		if(StringUtils.isNotBlank(paramsPd.getString("attach"))) {
			params.put("attach", paramsPd.getString("attach"));   //附加数据
		}
		//获取签名
		String sign = generateSign(params, partnerkey);  
		
		params.put("sign", sign); //签名
		String xml = generateXmlStr(params);  //获取接口满足格式要求的接口参数
		
		//调用统一下单接口获取 预支付ID: prepay_id
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		String prepay_id = "";
		try {
			Map<String, Object> map = wxHttpPost(createOrderURL, xml);  
			String resultCode = (String) map.get("result_code");
			if("SUCCESS".equals(resultCode)) {
				prepay_id = (String) map.get("prepay_id");
				if(StringUtils.isBlank(prepay_id)) {
					result.put("code", false);
					result.put("msg", "预支付交易会话标识获取异常");
					return result;
				}
			}else {
				String errCode = (String) map.get("err_code");
				String msg = buildUPIErrMsg(errCode);  //构建统一支付接口异常消息描述
				result.put("code", false);
				result.put("msg", msg);
				return result;
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.put("code", false);
			result.put("msg", "微信支付出错啦!!!");
			return result;
		}
		
		Map<String, String> signParams = new HashMap<>();
		String timeStamp = Sha1Util.getTimeStamp();  //时间戳
		String nonceStr = Sha1Util.getNonceStr();  //随机串
		signParams.put("appId", APPID);
		signParams.put("nonceStr", nonceStr);
		signParams.put("package", "prepay_id="+prepay_id);
		signParams.put("timeStamp", timeStamp);
		signParams.put("signType", "MD5");
		String paySign = generateSign(signParams, partnerkey);  //获取支付数据签名
		
		//构建需要返回的支付参数
		PageData data = new PageData();
		data.put("timeStamp", timeStamp);
		data.put("nonceStr", nonceStr);
		data.put("package", "prepay_id="+prepay_id);
		data.put("signType", "MD5");
		data.put("paySign", paySign);
		
		result.put("code", true);
		result.put("data", data);
		result.put("msg", "支付参数获取成功");
		return result;
	}

	/**
	 * 生成签名
	 * @param params 参数 
	 * @param partnerkey  商户号密钥
	 * @return
	 */
	public static String generateSign(Map<String, String> params, String partnerkey) {
		String result = "";
	    try {
	        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(params.entrySet());
	        // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
	        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {

	            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
	                return (o1.getKey()).toString().compareTo(o2.getKey());
	            }
	        });
	        // 构造签名键值对的格式
	        StringBuffer sb = new StringBuffer();
	        for (Map.Entry<String, String> item : infoIds) {
	        	String key = item.getKey();
	            if (!(null == key || "".equals(key) || "sign".equals(key) || "key".equals(key))) {
	                String val = item.getValue();
	                if (!(null == val || "".equals(val))) {
	                    sb.append(key + "=" + val + "&");
	                }
	            }
	        }
	        sb.append("key=" + partnerkey);
	        //进行MD5加密
	        result = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
	    } catch (Exception e) {
	        return null;
	    }
	    return result;
	}
微信小程序调起支付: 微信API描述
wx.requestPayment({
      'nonceStr': params.nonceStr,
      'package': params.package,
      'paySign': params.paySign,
      'signType': params.signType,
      'timeStamp': params.timeStamp,
      'success': function (res) {
        支付成功后处理逻辑
      },
      'fail': function (res) { },
      'complete': function (res) { }
    })
支付成功后的回调

在统一下单输入了回调的URL,在成功后,微信会回调你多次,一直到成功为止。请参考自身业务进行编写代码。【回调地址在同一支付接口中设置】

/**
	 * 微信支付结果通知回调接口
	 * 
	 * @return
	 */
	@RequestMapping(value = "/wxPayCallBack")
	@ResponseBody
	public String eNotifys(HttpServletRequest request, HttpServletResponse response) {
		logger.info("==================小程序支付结果通知回调=========================");
		BufferedReader br;
		try {
			br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
			String line = null;
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			Document doc = DocumentHelper.parseText(sb.toString()); // 将字符串转为XML
			Element root = doc.getRootElement(); // 获取根节点
			
			String resultCode = root.elementTextTrim("result_code");  //支付状态响应标识 SUCCESS/FAIL
			String outTradeNo = root.elementTextTrim("out_trade_no");  //商户订单号
			String transactionId = root.elementTextTrim("transaction_id");  //微信支付订单号
			String totalFee = root.elementTextTrim("total_fee");  //订单金额
			String cashFee = root.elementTextTrim("cash_fee");  //现金支付金额
			String attach = root.elementTextTrim("attach");  //商家数据包, 原样返回
			//SUCCESS/FAIL
		
			// 根据微信的result_code判断微信端是否支付成功
			if ("SUCCESS".equals(resultCode)) { 
				String xml = WxAppletPayUtil.successXML("SUCCESS", "");
				response.getWriter().write(xml);
				logger.error("商户订单号: 【" + outTradeNo + "】支付成功");
				
				//业务逻辑处理
				
				
				
			}else if ("FAIL".equals(resultCode)) {
				String errCode = root.elementTextTrim("err_code");
				String errCodeDes = root.elementTextTrim("err_code_des");
				logger.error("商户订单号: 【" + outTradeNo + "】支付失败,  "+"描述:【errCode:"+errCode+", errCodeDes:"+errCodeDes+"】");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}