Java实现字节小程序微信担保支付及回调超详细

1:在平台申请支付功能,设置回调接口,token

2:服务端支付下单

        加密工具类

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
*加密工具类
*/
public class DouYinUtil {

    // 支付密钥值
    private static final String SALT = "担保交易设置中的SALT";

    // paramsMap 参数含义解释同 golang
    public static String getSign(Map<String, Object> paramsMap) {
        List<String> paramsArr = new ArrayList<>();
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            String key = entry.getKey();
            if (key.equals("other_settle_params")) {
                continue;
            }
            String value = entry.getValue().toString();

            value = value.trim();
            if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
                value = value.substring(1, value.length() - 1);
            }
            value = value.trim();
            if (value.equals("") || value.equals("null")) {
                continue;
            }
            switch (key) {
                case "app_id":
                case "thirdparty_id":
                case "sign":
                    break;
                default:
                    paramsArr.add(value);
                    break;
            }
        }
        paramsArr.add(SALT);
        Collections.sort(paramsArr);
        StringBuilder signStr = new StringBuilder();
        String sep = "";
        for (String s : paramsArr) {
            signStr.append(sep).append(s);
            sep = "&";
        }
        return md5FromStr(signStr.toString());
    }

    public static String md5FromStr(String inStr) {
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }

        byte[] byteArray = inStr.getBytes(StandardCharsets.UTF_8);
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuilder hexValue = new StringBuilder();
        for (byte md5Byte : md5Bytes) {
            int val = ((int) md5Byte) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

    public static String getSha1(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes(PublicFinal.S_UTF_8));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] buf = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            // TODO: handle exception
            return null;
        }
    }
}

支付下单/支付回调

@Autowired
private RestTemplate restTemplate;

/**
     * 获取支付的请求参数
     */
    @ApiOperation(value = "获取支付的请求参数")
    @GetMapping("prepay")
    public Object payPrepay(Integer orderId) {
        logger.info("---------orderId:{}",orderId);
        Map<String, Object> parame = new LinkedHashMap<>();
        //抖音小程序app
        parame.put("app_id", "appid");
        // 商户订单编号
        parame.put("out_order_no", "订单号,需平台唯一");
        //支付金额
        parame.put("total_amount", new BigDecimal(1).multiply(new BigDecimal(100)).intValue());
        // 商品标题
        parame.put("subject","商品名称");
        // 商品描述(不能为空)
        parame.put("body", "商品描述");
        // 回调地址(与支付设置中一致)
        parame.put("notify_url", "担保交易设置中的回调地址");
        // 时间
        parame.put("valid_time",900);
        // 支付密钥
        String sign = DouYinUtil.getSign(parame);
        logger.info("支付下单密钥签名:{}",sign);
        // 数字签证
        parame.put("sign", sign);
        String res = restTemplate.postForObject("https://developer.toutiao.com/api/apps/ecpay/v1/create_order",parame,String.class);
        logger.info("res-----------:{}",res);
        JSONObject sessionData1 = JSON.parseObject(res);
        if ("0".equalsIgnoreCase(sessionData1.getString("err_no"))) {
            logger.info("支付成功");
            JSONObject sessionData = sessionData1.getJSONObject("data");
            Map<String, Object> resultObj = new HashMap();
            String prepayId = sessionData.getString("order_id");
            resultObj.put("err_no",sessionData1.getString("err_no"));
            resultObj.put("order_id",prepayId);
            resultObj.put("order_token",sessionData.getString("order_token"));
            return resultObj;
        }else{
            logger.info("支付失败");
            Map<String, Object> resultObj = new HashMap<>();
            resultObj.put("err_no",sessionData1.getString("err_no"));
            return resultObj;
        }
    }


    @ApiOperation(value = "抖音微信订单回调接口")
    @RequestMapping(value = "/notify", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
    @ResponseBody
    public Object dynotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=UTF-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            InputStream in = request.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.close();
            in.close();
            String responseJson = new String(out.toByteArray(),"utf-8");
            logger.info("responseJson:{}",responseJson);
            JSONObject jsonObject = JSONObject.parseObject(responseJson);
            JSONObject msgJson = jsonObject.getJSONObject("msg");
            String resultCode = jsonObject.getString("type");
            if ("payment".equalsIgnoreCase(resultCode)) {
                List<String> sortedString = new ArrayList<>();
                //token
                sortedString.add("token");
                //时间戳
                sortedString.add(jsonObject.getString("timestamp"));
                //随机数
                sortedString.add(jsonObject.getString("nonce"));
                //msg
                sortedString.add(jsonObject.getString("msg"));
                Collections.sort(sortedString);
                StringBuilder sb = new StringBuilder();
                sortedString.forEach(sb::append);
                String msg_signature = jsonObject.getString("msg_signature");
                String sign = DouYinUtil.getSha1(sb.toString().trim());
                logger.info("支付回调接口密钥签名:{}",sign);
                if(!sign.equals(msg_signature)) {//判断签名
                    JSONObject resultJson = new JSONObject();
                    resultJson.put("err_no",8);
                    resultJson.put("err_tips","error");
                    return resultJson.toString();
                }
                JSONObject resultJson = new JSONObject();
                resultJson.put("err_no",0);
                resultJson.put("err_tips","success");
                return resultJson.toString();
            } else {
                //订单编号
                String outTradeNo = msgJson.getString("cp_orderno");
                logger.error("订单" + outTradeNo + "支付失败");
                JSONObject resultJson = new JSONObject();
                resultJson.put("err_no",0);
                resultJson.put("err_tips","error");
                return resultJson.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject resultJson = new JSONObject();
            resultJson.put("err_no",8);
            resultJson.put("err_tips","error");
            return resultJson.toString();
        }
    }

注意:支付下单签名加密方式为Md5,支付回调接口签名为Sha1,加密参数顺序不能乱

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值