微信&支付宝支付

1、微信支付

        <!--    微信 pay    -->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-apache-httpclient</artifactId>
            <version>0.2.2</version>
        </dependency>
@Data
@Configuration
@ConfigurationProperties(prefix = "wchatpay")
public class WechatPayConfig {

    //微信APPID
    private String appid;
    //微信商户号
    private String mchid;
    //微信支付通知
    private String notifyUrl;
    //微信支付 证书编号
    private String mchSerialNo;
//    证书路径
    private String merchantPrivateKey;
    //商户APIV3密钥
    private String apiV3key;

    private PrivateKey privateKey;
    private WechatPayHttpClientBuilder builder;
    private AutoUpdateCertificatesVerifier verifier;
    private AesUtil aesUtil;

    @Bean
    public void initWechatPay() throws IOException {
        FileInputStream fis = new FileInputStream(merchantPrivateKey);
        aesUtil = new AesUtil(apiV3key.getBytes(StandardCharsets.UTF_8));
        privateKey = PemUtil.loadPrivateKey(fis);
        fis.close();
        //不需要传入微信支付证书了
        verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(mchid, new PrivateKeySigner(mchSerialNo, privateKey)),
                apiV3key.getBytes(StandardCharsets.UTF_8));
        builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchid, mchSerialNo, privateKey)
                .withValidator(new WechatPay2Validator(verifier));
    }

}
public class WechatUtil {

    /**
     * 微信调起支付参数
     * @param jsonObject
     * @param wxpayAppid
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static JSONObject WechatPayTuneUp(JSONObject jsonObject, String wxpayAppid, PrivateKey privateKey) throws Exception {
        System.out.println("success,return body = " + jsonObject.toJSONString());
        //预支付交易会话标识
        String prepayId = jsonObject.getString("prepay_id");
        //随机字符串
        String nonceStr = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
        //时间戳
        long timestamp = System.currentTimeMillis() / 1000;
        //从下往上依次生成
        String message = buildMessage(wxpayAppid, timestamp, nonceStr, prepayId);
        //签名
        String signature = sign(message.getBytes("utf-8"), privateKey);

        JSONObject params = new JSONObject();
        params.put("appId", wxpayAppid);
        params.put("timeStamp", timestamp);
        params.put("nonceStr", nonceStr);
        params.put("package", "prepay_id=" + prepayId);
        params.put("signType", "RSA");
        params.put("paySign", signature);
        return params;
    }

    private static String sign(byte[] message, PrivateKey privateKey) throws InvalidKeyException, SignatureException, NoSuchAlgorithmException {
        //签名方式
        Signature sign = Signature.getInstance("SHA256withRSA");
        //私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
        sign.initSign(privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 按照前端签名文档规范进行排序,\n是换行
     * @param appId
     * @param timestamp
     * @param nonceStr
     * @param prepayId
     * @return
     */
    private static String buildMessage(String appId, long timestamp, String nonceStr, String prepayId) {
        return appId + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + "prepay_id=" + prepayId + "\n";
    }

    public static String success() {
        JSONObject jsonResponse = new JSONObject();
        jsonResponse.put("code", "SUCCESS");
        jsonResponse.put("message", "成功");
        return jsonResponse.toString();
    }

    public static String fail() {
        JSONObject jsonResponse = new JSONObject();
        jsonResponse.put("code", "FAIL");
        jsonResponse.put("message", "失败");
        return jsonResponse.toString();
    }

}
public interface IWechatPayService {

    /**
     * 生成预支付交易单 - 小程序支付
     * @param openid 用户openid
     * @param paymentNo 支付流水编号
     * @param goodsName 商品名称
     * @param totalFee 订单金额(单位:分)
     */
    JSONObject wechatPayXcxPay(String openid, String paymentNo, String goodsName, int totalFee) throws Exception;

    /**
     *  验签 & 解密
     * @param wechatpaySerial
     * @param wechatpaySignature
     * @param wechatpayTimestamp
     * @param wechatpayNonce
     * @param callback
     * @return
     */
    PayNotifyResDTO decryptBody(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String callback) throws Exception;

    /**
     * 根据支付流水编号,查询订单信息
     * @param paymentNo
     * @return
     */
    PayNotifyResDTO getPayOrderInfo(String paymentNo);

}
@Service
public class WechatPayServiceImpl implements IWechatPayService {

    @Autowired
    private WechatPayConfig wechatPayConfig;

    //    小程序下单地址
    public static final String WECHAT_PAY_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
//    查询订单地址
    public static final String WECHAT_GET_ORDER = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}";

    @Override
    public JSONObject wechatPayXcxPay(String openid, String orderSn, String goodsName, int totalFee) throws Exception {
        CloseableHttpClient httpClient = wechatPayConfig.getBuilder().build();
        try {
            //请求URL
            HttpPost httpPost = new HttpPost(WECHAT_PAY_URL);
            // 请求body参数
            JSONObject reqJson = new JSONObject();
            JSONObject amountJson = new JSONObject();
            amountJson.put("total", totalFee);
            amountJson.put("currency", "CNY");
            reqJson.put("amount", amountJson);
            reqJson.put("mchid", wechatPayConfig.getMchid());
            reqJson.put("description", goodsName);
            reqJson.put("notify_url", wechatPayConfig.getNotifyUrl());
            JSONObject payerJson = new JSONObject();
            payerJson.put("openid", openid);
            reqJson.put("payer", payerJson);
            reqJson.put("out_trade_no", orderSn);
            reqJson.put("goods_tag", "WXG");
            reqJson.put("appid", wechatPayConfig.getAppid());
            System.out.println("reqJson = " + reqJson.toJSONString());
            StringEntity entity = new StringEntity(reqJson.toJSONString(), "utf-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
            httpPost.setHeader("Accept", "application/json");
            //完成签名并执行请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
            if (jsonObject.containsKey("prepay_id")) {
                return WechatUtil.WechatPayTuneUp(jsonObject, wechatPayConfig.getAppid(), wechatPayConfig.getPrivateKey());
            } else {
                System.out.println("return body = " + jsonObject.toJSONString());
                throw new IOException("request failed");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpClient.close();
        }
        return null;
    }

    /**
     * 验签
     * @return
     */
    private Boolean verify(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String callback) {
        //按照文档要求拼接验签串
        String verifySignature = wechatpayTimestamp + "\n"
                + wechatpayNonce + "\n"
                + callback + "\n";
        //使用官方验签工具进行验签
        return wechatPayConfig.getVerifier().verify(wechatpaySerial, verifySignature.getBytes(), wechatpaySignature);
    }

    @Override
    public PayNotifyResDTO decryptBody(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp,
                                       String wechatpayNonce, String callback) throws Exception {
        //判断验签的结果
        if (!verify(wechatpaySerial, wechatpaySignature, wechatpayTimestamp, wechatpayNonce, callback)) {
            //验签失败,应答接口
            return null;
        }

        JSONObject parseObject = JSONObject.parseObject(callback);
        if ("TRANSACTION.SUCCESS".equals(parseObject.getString("event_type"))
                && "encrypt-resource".equals(parseObject.getString("resource_type"))) {
            //通知的类型,支付成功通知的类型为TRANSACTION.SUCCESS
            //通知的资源数据类型,支付成功通知为encrypt-resource
            JSONObject resourceJson = JSONObject.parseObject(parseObject.getString("resource"));
            String associated_data = resourceJson.getString("associated_data");
            String nonce = resourceJson.getString("nonce");
            String ciphertext = resourceJson.getString("ciphertext");

            //解密,如果这里报错,就一定是APIv3密钥错误
            String resourceData = wechatPayConfig.getAesUtil().decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
            System.out.println("解密后=" + resourceData);
            JSONObject resource = JSONObject.parseObject(resourceData);
            if (resource.containsKey("out_trade_no")) {
                /**支付成功,补充业务**/
                PayNotifyResDTO resDTO = new PayNotifyResDTO();
//            第三方支付id
                resDTO.setNotifyId(parseObject.getString("id"));
//                商户订单号
                resDTO.setOutTradeNo(resource.getString("out_trade_no"));
//                微信支付订单号
                resDTO.setTradeNo(resource.getString("transaction_id"));
                resDTO.setTradeStatus(resource.getString("trade_state"));
                return resDTO;
            }
        }
        return null;
    }

    @Override
    public PayNotifyResDTO getPayOrderInfo(String paymentNo) {
        //返回模型
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = wechatPayConfig.getBuilder().build();
        try {
            String str = WECHAT_GET_ORDER.replace("{out_trade_no}", paymentNo) + "?mchid=" + wechatPayConfig.getMchid();
            HttpGet httpGet = new HttpGet(str);
            httpGet.addHeader("Accept", "application/json");
            response = httpClient.execute(httpGet);
            if (response != null) {
                JSONObject resource = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
                System.out.println("resource = " + resource);
                PayNotifyResDTO resDTO = new PayNotifyResDTO();
//                商户订单号
                resDTO.setOutTradeNo(resource.getString("out_trade_no"));
//                微信支付订单号
                resDTO.setTradeNo(resource.getString("transaction_id"));
//                状态
                resDTO.setTradeStatus(resource.getString("trade_state"));
                return resDTO;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                httpClient.close();
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}
    /**
     * 微信回调
     * @param wechatpaySerial
     * @param wechatpaySignature
     * @param wechatpayTimestamp
     * @param wechatpayNonce
     * @param callback
     * @return
     */
    @PostMapping(value = "wechat")
    public String wechatPayNotify(@RequestHeader("Wechatpay-Serial") String wechatpaySerial,
                                  @RequestHeader("Wechatpay-Signature") String wechatpaySignature,
                                  @RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
                                  @RequestHeader("Wechatpay-Nonce") String wechatpayNonce,
                                  @RequestBody String callback) {
        try {
//            回调通知验签和解密
            PayNotifyResDTO resDTO = wechatPayService.decryptBody(wechatpaySerial, wechatpaySignature, wechatpayTimestamp, wechatpayNonce, callback);
            if (resDTO == null) {
                return WechatUtil.fail();
            }
//            回调业务

        } catch (Exception e) {
            e.printStackTrace();
            return WechatUtil.fail();
        }
        return WechatUtil.success();
    }

2、支付宝支付

        <!-- 阿里 pay -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-easysdk</artifactId>
            <version>2.1.0</versionk>
        </dependency>
@Data
@Configuration
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {

    /**应用ID*/
    private String appId;

    /** 应用私钥 */
    private String merchantPrivateKey;

    /** 应用公钥证书文件路径 */
    private String merchantCertPath;

    /** 支付宝公钥证书文件路径 */
    private String alipayCertPath;

    /** 应用公钥证书文件路径 */
    private String alipayRootCertPath;

    /** 回调地址 */
    private String notifyUrl;

    /**
     * 支付宝支付,配置类
     * @return
     */
    @Bean
    public Config getOptions() {
        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = "openapi.alipay.com";
        config.signType = "RSA2";
        /**<-- 请填写您的AppId,例如:2019091767145019 -->*/
        config.appId = appId;
        // 请填写您的应用私钥
        config.merchantPrivateKey = merchantPrivateKey;
        //注:证书文件路径支持设置为文件系统中的路径或CLASS_PATH中的路径,优先从文件系统中加载,加载失败后会继续尝试从CLASS_PATH中加载
        config.merchantCertPath =  merchantCertPath; //"<-- 请填写您的应用公钥证书文件路径,例如:/foo/appCertPublicKey_2019051064521003.crt -->";
        config.alipayCertPath = alipayCertPath; //"<-- 请填写您的支付宝公钥证书文件路径,例如:/foo/alipayCertPublicKey_RSA2.crt -->";
        config.alipayRootCertPath =  alipayRootCertPath; //"<-- 请填写您的支付宝根证书文件路径,例如:/foo/alipayRootCert.crt -->";
        //注:请填写您的支付宝公钥: 如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
//        config.alipayPublicKey = "";
        //可设置异步通知接收服务地址(可选):<-- 请填写您的支付类接口异步通知接收服务地址,例如:https://www.test.com/callback -->
        config.notifyUrl = notifyUrl;
        //可设置AES密钥,调用AES加解密相关接口时需要(可选)
        config.encryptKey = "";
        return config;
    }

    @Bean
    public void initAliPay() {
        Factory.setOptions(getOptions());
    }

}
public interface IAliPayService {

    /**
     * 支付宝APP支付
     * @param subject 订单介绍
     * @param outTradeNo 订单编号
     * @param totalAmount 订单价格(元,小数点后面两位)
     * @return
     */
    String aliPayAppPay(String subject, String outTradeNo, String totalAmount);

    /**
     * 回调验签
     * @return
     */
    PayNotifyResDTO verifyNotify(Map<String, String> data);

    /**
     * 查询订单信息
     * @param outTradeNo
     * @return
     */
    PayNotifyResDTO getPayOrderInfo(String outTradeNo);

}
@Slf4j
@Service
public class AliPayServiceImpl implements IAliPayService {

    @Override
    public String aliPayAppPay(String subject, String outTradeNo, String totalAmount) {
//        App支付
        try {
            AlipayTradeAppPayResponse response = Factory.Payment.App().pay(subject, outTradeNo, totalAmount);
            if (ResponseChecker.success(response)) {
                log.info("{}:支付宝APP支付,发起成功", outTradeNo);
                return response.getBody();
            } else {
                log.info("{}:支付宝App支付,发起失败:{}", outTradeNo, response.body);
            }
        } catch (Exception e) {
            log.error("{}:支付宝App支付异常:{}", outTradeNo, e);
        }
        return null;
    }

    @Override
    public PayNotifyResDTO verifyNotify(Map<String, String> data) {
        try {
            Boolean aBoolean = Factory.Payment.Common().verifyNotify(data);
            if (!aBoolean) {
                return null;
            }
//          封装返回参数
            PayNotifyResDTO resDTO = new PayNotifyResDTO();
            resDTO.setOutTradeNo(data.get("out_trade_no"));
            resDTO.setNotifyId(data.get("notify_id"));
            resDTO.setTradeNo(data.get("trade_no"));
            resDTO.setTradeStatus(data.get("trade_status"));
            return resDTO;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public PayNotifyResDTO getPayOrderInfo(String outTradeNo) {
        try {
            AlipayTradeQueryResponse response = Factory.Payment.Common().query(outTradeNo);
            System.out.println("response = " + JSONObject.parseObject(response.getBody()));
            if (ResponseChecker.success(response)) {
                log.info("{}:查询App支付订单,成功", outTradeNo);
                JSONObject data = JSONObject.parseObject(response.getBody());
                PayNotifyResDTO resDTO = new PayNotifyResDTO();
                resDTO.setOutTradeNo(data.getString("out_trade_no"));
                resDTO.setTradeNo(data.getString("trade_no"));
                resDTO.setTradeStatus(data.getString("trade_status"));
                return resDTO;
            } else {
                log.info("{}:查询App支付订单,失败:{}", outTradeNo, response.getSubMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
    /**
     * 阿里支付回调
     * @param data
     * @return
     */
    @PostMapping("ali")
    public String aliPayNotify(@RequestParam Map<String, String> data) {
        PayNotifyResDTO resDTO = aliPayService.verifyNotify(data);
        if (resDTO == null) {
            return "sign fail";
        }
//            回调业务

        return "success";
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值