欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java微信小程序支付

程序员文章站 2022-06-14 23:28:21
...

微信支付的流程:统一下单----->前端支付------>支付回调
流程很简单首先先看下官方统一下单文档:
官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

java微信小程序支付
官方统一下单接口,只需要我们后端调用这个接口就能完成统一下单,接下来是参数:
java微信小程序支付
java微信小程序支付
java微信小程序支付
参数中有必传和非必传根据我们的需要选定好参数,我做的是小程序所以我需要的参数都有:

					"<xml>"
                    +"<appid>小程序appid</appid>"
                    +"<mch_id>商户号</mch_id>"
                    +"<nonce_str>"+nonce_str+"</nonce_str>"
                    +"<body>支付测试</body>"
                    +"<out_trade_no>"+id+"</out_trade_no>"
                    +"<total_fee>1</total_fee>"
                    +"<spbill_create_ip>终端IP</spbill_create_ip>"
                    +"<notify_url>"+notify_url+"</notify_url>"
                    +"<trade_type>JSAPI</trade_type>"
                    +"<openid>"+openid+"</openid>"
                    +"<sign>"+sign+"</sign>"
                    +"</xml>";

这是最后传的参数,微信支付的参数和返回值都是xml格式

下面上代码
用的pom依赖

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.48</version>
		</dependency>
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>

主体方法

@Override
    public JSONObject payOrder(String id,String openid) {
        String nonce_str= UUID.randomUUID().toString().replace("-", "");//32位随机数我直接用的uuid
        String notify_url = "https://localhost:1013/pay_back";//微信回调的地址,必须是外网能直接访问的https接口
        String sign = sign("wx161332eed75bbba8","1521752201",nonce_str,"支付测试",
                id,"1","47.92.254.214",notify_url,"JSAPI",openid);//签名方法
        String aa ="<xml>"
                    +"<appid>小程序appid</appid>"
                    +"<mch_id>商户号</mch_id>"
                    +"<nonce_str>"+nonce_str+"</nonce_str>"
                    +"<body>支付测试</body>"
                    +"<out_trade_no>"+id+"</out_trade_no>"
                    +"<total_fee>1</total_fee>"
                    +"<spbill_create_ip>47.92.254.214</spbill_create_ip>"
                    +"<notify_url>"+notify_url+"</notify_url>"
                    +"<trade_type>JSAPI</trade_type>"
                    +"<openid>"+openid+"</openid>"
                    +"<sign>"+sign+"</sign>"
                    +"</xml>";
        String bb = HttpClientUtil.doPostJson("https://api.mch.weixin.qq.com/pay/unifiedorder",aa);//请求微信统一下单接口 这样统一下单就完成了 如果成功会返回我们支付时候需要的值,将前端支付需要的值返回就可以了
        System.out.println(bb.toString());
        //返回值是xml格式,所以要进行转化
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(bb);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Map<String,String> map = new HashMap<>();
        Element root = doc.getRootElement();
        //前端发起支付的需要的签名
        String paySign = paySing("小程序appid",String.valueOf(new Date().getTime()),
                UUID.randomUUID().toString().replace("-", ""),root.element("prepay_id").getTextTrim(),
                "MD5");
        map.put("package","prepay_id="+root.element("prepay_id").getTextTrim());//统一下单返回的预支付交易会话标识
        map.put("timeStamp", String.valueOf(new Date().getTime()));//时间戳
        map.put("nonceStr", UUID.randomUUID().toString().replace("-", ""));//随机字符串
        map.put("signType", "MD5");//加密方式
        map.put("paySign", paySign);//前端发起支付的签名
        //打包返回给前端
        JSONObject end = new JSONObject();
        end.put("status","200");
        end.put("prepay_order",map);
        end.put("order_id",id);
        return end;
    }

同意下签名方法

//统一下单签名算法
    private String sign(String appid,String mch_id,String nonce_str,String body,String out_trade_no,
                        String total_fee,String spbill_create_ip,String notify_url,String trade_type,String openid){
        String A="appid="+appid+"&body="+body+"&mch_id="+mch_id+"&nonce_str="+nonce_str+"&notify_url="+notify_url+
                "&openid="+openid+"&out_trade_no="+out_trade_no+"&spbill_create_ip="+spbill_create_ip+"&total_fee="+
                total_fee+"&trade_type="+trade_type;
        String SignTemp=A+"&key=sfsdf34534wrrewergdfghrty4564564";
        String sign = MD5Util.getMD5(SignTemp).toUpperCase();
        return sign;
    }

发起支付签名算法

 //发起支付签名算法
    private String paySing(String appid,String timeStamp,String nonceStr,String prepay_id,String signType){
        String A = "appid="+appid+"&nonceStr="+nonceStr+"&package="+prepay_id+"&signType="+signType+
                "&timeStamp="+timeStamp;
        String sign = MD5Util.getMD5(A).toUpperCase();
        return sign;
    }

MD5加密工具类

package com.mengxiang.utils;

import java.security.MessageDigest;

public class MD5Util {

	private final static String[] HEXDIGITS = { "0", "1", "2", "3", "4", "5",
			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

	public final static String getMD5(String str) {
		if (str != null) {
			try {
				// 创建具有指定算法名称的信息摘要
				MessageDigest md = MessageDigest.getInstance("MD5");
				// 使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
				byte[] results = md.digest(str.getBytes()); // 将得到的字节数组变成字符串返回
				StringBuffer resultSb = new StringBuffer();
				String a = "";
				for (int i = 0; i < results.length; i++) {
					int n = results[i];
					if (n < 0)
						n = 256 + n;
					int d1 = n / 16;
					int d2 = n % 16;
					a = HEXDIGITS[d1] + HEXDIGITS[d2];
					resultSb.append(a);
				}
				return resultSb.toString();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return null;
	}

	private static String byteArrayToHexString(byte b[]) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++)
			resultSb.append(byteToHexString(b[i]));

		return resultSb.toString();
	}

	private static String byteToHexString(byte b) {
		int n = b;
		if (n < 0)
			n += 256;
		int d1 = n / 16;
		int d2 = n % 16;
		return HEXDIGITS[d1] + HEXDIGITS[d2];
	}

	public static String MD5Encode(String origin, String charsetname) {
		String resultString = null;
		try {
			resultString = new String(origin);
			MessageDigest md = MessageDigest.getInstance("MD5");
			if (charsetname == null || "".equals(charsetname))
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes()));
			else
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes(charsetname)));
		} catch (Exception exception) {
		}
		return resultString;
	}

	/***
	 * MD5加码 生成32位md5码
	 */
	public static String string2MD5(String inStr) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (Exception e) {
			System.out.println(e.toString());
			e.printStackTrace();
			return "";
		}
		char[] charArray = inStr.toCharArray();
		byte[] byteArray = new byte[charArray.length];

		for (int i = 0; i < charArray.length; i++)
			byteArray[i] = (byte) charArray[i];
		byte[] md5Bytes = md5.digest(byteArray);
		StringBuffer hexValue = new StringBuffer();
		for (int i = 0; i < md5Bytes.length; i++) {
			int val = ((int) md5Bytes[i]) & 0xff;
			if (val < 16)
				hexValue.append("0");
			hexValue.append(Integer.toHexString(val));
		}
		return hexValue.toString();

	}

	// 测试主函数
	public static void main(String args[]) {
		String s = new String("ale123123");
		System.out.println("原始:" + s);
		System.out.println("MD5后:" + string2MD5(s));
	}
}

回调接口

/**
     * 接收返回值
     * */
    @RequestMapping("/pay_back")
    @ResponseBody
    public String pay_back(HttpServletRequest req, HttpServletResponse resp){
        InputStream ins = null;
        try {
            ins = req.getInputStream();
            byte[] rebyte = readStream(ins);
            String remess = new String(rebyte);
            System.out.println("XML报文内容为:" + remess);
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return "success";
    }

接收返回值主要就是将接收到的xml格式解析,读取返回值,有一点主意微信会回调多次,所以需要自行根据业务判断数据是否已经修改

相关标签: 日常笔记