java 微信小程序支付 V2

  • 把sdk复制进项目中,如下图

  • 写一个类继承微信SDK中的 WXPayConfig
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * 继承微信sdk的配置类
 */
@Service
public class MyWxPayConfig extends WXPayConfig {
    private byte[] certData;
    private String appId = "";//微信提供的appid
    private String wxPayKey = "";//微信提供的密钥
    private String wxPayMchId = "";//微信提供的商务id
    //本地证书路径
    private String linuxOS = "/mnt/mall-service/pay/wechatKey/apiclient_cert.p12";
    private String windowsOS = "D:\\work\\mj_mall\\jeecg-cloud\\key\\apiclient_cert.p12";

    @Override
    public String getAppID() {
        return appId;
    }

    @Override
    public String getMchID() {
        return wxPayMchId;
    }

    @Override
    public String getKey() {
        return wxPayKey;
    }

    @Override
    public InputStream getCertStream() {
        return new ByteArrayInputStream(this.certData);
    }

    @Override
    public IWXPayDomain getWXPayDomain() {
        IWXPayDomain iwxPayDomain = new IWXPayDomain() {
            @Override
            public void report(String domain, long elapsedTimeMillis, Exception ex) {

            }

            @Override
            public DomainInfo getDomain(WXPayConfig config) {
                return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);
            }
        };
        return iwxPayDomain;
    }

    /**
     * 构造方法读取证书, 通过getCertStream 可以使sdk获取到证书
     */
    public MyWxPayConfig() throws Exception {
        //通过服务操作系统判断使用的证书地址,win 和 linux 路径不通
        String property = System.getProperty("os.name");
        File file = null;
        if (property.contains("Windows") || property.contains("windows")) {
            file = new File(windowsOS);
        } else {
            file = new File(linuxOS);
        }
        InputStream certStream = new FileInputStream(file);
        this.certData = new byte[(int) file.length()];
        certStream.read(this.certData);
        certStream.close();
    }

}
  • 发起支付前需要统一下单
@Autowired
private MyWxPayConfig myWxPayConfig;

public Result<Object> wxPayV2SubmitOrder(@RequestParam(name = "orderId") String orderId) {
    try {
        Order order = orderApi.getOrderInfoById(orderId);
        Customer customer = customerApi.getCustomerById(order.getCustomerId());
        SysUser sysUser = sysUserRemoteApi.getSysUser(customer.getUserId());

        //  统一下单,myWxPayConfig是继承SDK的那个类
        WXPay wxpay = new WXPay(myWxPayConfig);
        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "统一下单");
        data.put("out_trade_no", order.getOrderCode()); // 订单唯一编号, 不允许重复
        //data.put("total_fee", String.valueOf(order.getOrderPrice().intValue())); // 订单金额, 单位分
        data.put("total_fee", String.valueOf(1)); // 订单金额, 单位分
        data.put("spbill_create_ip", oConvertUtils.getIpAddrByRequest(SpringContextUtils.getHttpServletRequest())); // 下单ip
        data.put("openid", sysUser.getThirdId()); // 微信公众号统一标示openid
        data.put("notify_url", payNotifyUrl); // 订单结果通知, 微信主动回调此接口
        data.put("trade_type", "JSAPI"); // 固定填写
        //下单
        Map<String, String> response = wxpay.unifiedOrder(data);
        logger.info(JSONObject.toJSONString(response));
        String returnCode = response.get("return_code");
        String resultCode = response.get("result_code");
        String returnMsg = response.get("return_msg");
        String prepayId = response.get("prepay_id");

        if (CollUtil.isEmpty(response) || !returnCode.equals("SUCCESS") ||
                !resultCode.equals("SUCCESS") || !returnMsg.equals("OK") || null == prepayId) {
            //微信支付下单失败
            return Result.error(response.get("err_code_des"));
        }
        //下单成功去获取调起微信支付参数
        Map<String, String> map = wechatCreatePay(prepayId);
        logger.info(JSONObject.toJSONString(map));
        if (CollUtil.isEmpty(map) || map.size() == 0) {
            return Result.error("支付调起参数异常");
        }
        return Result.ok(map);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
  • 获取微信支付调起参数
public Map<String, String> wechatCreatePay(String prepayId) {
    try {
        Map<String, String> wxPayMap = new HashMap<String, String>();
        wxPayMap.put("appId", myWxPayConfig.getAppID());
        wxPayMap.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
        wxPayMap.put("nonceStr", WXPayUtil.generateNonceStr());
        wxPayMap.put("package", "prepay_id=" + prepayId);
        wxPayMap.put("signType", "MD5");
        // 加密串中包括 appId timeStamp nonceStr package signType 5个参数, 通过sdk WXPayUtil类加密, 注意, 此处使用  MD5加密  方式
        String sign = WXPayUtil.generateSignature(wxPayMap, myWxPayConfig.getKey());
        //  返回给前端调起微信支付的必要参数
        Map<String, String> map = new HashMap<>();
        map.put("prepay_id", prepayId);
        map.put("paySign", sign);
        map.putAll(wxPayMap);
        return map;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
  • 参数获取成功后返回给前端调用就OK了

华丽的分割线---------------------------------------------------------------

  • 支付成功之后支付回调,提供给微信调用的
public String wechatPayCallback(HttpServletRequest request, HttpServletResponse response) {
    try {
        InputStream is = request.getInputStream();
        //将InputStream转换成String
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String resXml = sb.toString();
        logger.info("微信支付异步通知请求包------");
        logger.info(resXml);
        return wechatPayBack(resXml);
    } catch (Exception e) {
        logger.error("微信支付回调通知失败", e);
        String result = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
        return result;
    }
}
public String wechatPayBack(String xmlStr) {
    String xmlBack = "";
    Map<String, String> notifyMap = null;
    try {
        WXPay wxpay = new WXPay(myWxPayConfig);

        notifyMap = WXPayUtil.xmlToMap(xmlStr);         // 转换成map
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            logger.info("签名成功 \r\n" + JSONObject.toJSONString(notifyMap));
            // 签名正确
            // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
            String returnCode = notifyMap.get("return_code").trim();//状态
            //系统支付订单编号
            String outTradeNo = notifyMap.get("out_trade_no").trim();//订单号

            if (null == outTradeNo) {
                logger.info("微信支付回调失败订单号: {}", notifyMap);
                xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg></xml> ";
                return xmlBack;
            }
            //交易类型
            String tradeType = notifyMap.get("trade_type").trim();
            //付款银行
            String bankType = notifyMap.get("bank_type").trim();
            //微信支付订单号
            String transactionId = notifyMap.get("transaction_id").trim();
            //支付金额
            String cashFee = notifyMap.get("cash_fee").trim();
            //订单金额
            String totalFee = notifyMap.get("total_fee").trim();
            //支付时间
            String timeEnd = notifyMap.get("time_end").trim();
            //是否关注公众账号
            String isSubscribe = notifyMap.get("is_subscribe").trim();

            SimpleDateFormat format = new SimpleDateFormat("yyyy-HH-dd HH:mm:ss");
            Date date = new SimpleDateFormat("yyyy-HH-dd HH:mm:ss").parse(format.format(new SimpleDateFormat("yyyyHHddHHmmss").parse(timeEnd)));

            logger.info("微信支付回调成功订单号: {}", notifyMap);
            xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            return xmlBack;
        } else {
            logger.error("微信支付回调通知签名错误");
            xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
            return xmlBack;
        }
    } catch (Exception e) {
        logger.error("微信支付回调通知失败", e);
        xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
    }
    return xmlBack;
}
  • 支付流程基本跑完了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值