Java app接入微信和支付宝支付

1.支付宝支付
(1),配置
在这里插入图片描述
(2),方法Controller
@RestController
@RequestMapping("/alipay")
public class AlipayController {

@Resource
private AlipayViewService alipayViewService;
@Resource
private PayInfoMapper payInfoMapper;
/**
 * @Function: 去支付
 * @author: YangXueFeng
 * @Date:  2019/6/11 16:10
 */
@RequestMapping("/goToPay")
public synchronized JSONObject goToPay(@RequestBody ShoppingOrder shoppingOrder) throws IOException, AlipayApiException {
    JSONObject jsonObject=new JSONObject();
    jsonObject.put("data",alipayViewService.setGotoPayInfos(shoppingOrder));
    jsonObject.put(Constant.RETURN_STA, Constant.SUCCESS);
    jsonObject.put(Constant.RETURN_MSG, "成功");
    return jsonObject;
}

/**
 * @Function: 支付宝异步通知回调
 * @author: YangXueFeng
 * @Date:  2019/6/11 20:02
 */
@ResponseBody
@RequestMapping("/notify")
public String notify(HttpServletRequest request, HttpServletResponse response) throws ParseException {
    return alipayViewService.notify(request, response);
}

}

(3),方法service
/**

  • @author user
  • @program: haoyaogroup-erp
  • @description:
  • @date 2021/7/2 9:46
    /
    public interface AlipayViewService {
    /
    *
    • 付款
    • @param
    • @return 付款返回值
      /
      PayRequest setGotoPayInfos(ShoppingOrder shoppingOrder) throws AlipayApiException, UnsupportedEncodingException;
      /
      *
    • 付款异步通知调用地址
    • @param request 新增参数
    • @return 新增返回值
      */
      String notify(HttpServletRequest request, HttpServletResponse response) throws ParseException;
      }

(3),方法serviceImpl

@Service
@Transactional
public class AlipayViewServiceImpl implements AlipayViewService {
@Resource
private ShoppingOrderMapper orderMapper;
@Resource
private WxPayService wxPayService;
@Resource
private PayInfoMapper payInfoMapper;
@Resource
private ShoppingOrderMapper shoppingOrderMapper;
@Resource
private ShoppingOrderDetailMapper shoppingOrderDetailMapper;
@Resource
private ShoppingOrderStsRecordMapper shoppingOrderStsRecordMapper;
/**
* @Function: 去支付
* @author: YangXueFeng
* @Date: 2019/6/11 16:11
*/
@Override
public PayRequest setGotoPayInfos(ShoppingOrder shoppingOrder) throws AlipayApiException, UnsupportedEncodingException {

    if(StringUtils.isEmpty(String.valueOf(shoppingOrder.getOrderNum()))){
        throw new BusinessException(0,"订单编码不可为空");
    }

    if(StringUtils.isEmpty(String.valueOf(shoppingOrder.getTypes()))){
        throw new BusinessException(0,"支付方式不可为空");
    }


    PayInfo payInfo=new PayInfo();
    /* 查询订单信息 */
    List<ShoppingOrder> payParameter = orderMapper.selectList(shoppingOrder);
    //判断支付是否超时
    if(!CollectionUtils.isEmpty(payParameter)&& "60".equals(payParameter.get(0).getOrderSts())){
        throw new BusinessException(0,"订单已取消,不能支付");
    }
    PayRequest payRequest=new PayRequest();
   if("2".equals(shoppingOrder.getTypes())){//支付宝
        payInfo.setPayType("2");
        shoppingOrder=payParameter.get(0);
        //AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.url, AlipayConfig.app_id, AlipayConfig.private_key, AlipayConfig.format, AlipayConfig.charset, AlipayConfig.public_key, AlipayConfig.signtype);//支付宝需要的参数serverUrl、appId、private_key、format、charset、public_key、signType

     //构造client
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();

       //设置网关地址
        certAlipayRequest.setServerUrl(AlipayConfig.url);
       //设置应用Id
        certAlipayRequest.setAppId(AlipayConfig.app_id);
        //设置应用私钥
        certAlipayRequest.setPrivateKey(AlipayConfig.private_key);
         //设置请求格式,固定值json
        certAlipayRequest.setFormat(AlipayConfig.format);
        //设置字符集
        certAlipayRequest.setCharset(AlipayConfig.charset);
       //设置签名类型
        certAlipayRequest.setSignType(AlipayConfig.signtype);


        //设置应用公钥证书路径appCertPublicKey
        String in = Thread.currentThread().getContextClassLoader().getResource("").getPath()+"appCertPublicKey.crt";
        certAlipayRequest.setCertPath("/data/cert/appCertPublicKey.crt");
        //设置支付宝公钥证书路径alipayCertPublicKey
        String inAlipayCertPublicKey =Thread.currentThread().getContextClassLoader().getResource("").getPath()+"alipayCertPublicKey.crt";
        certAlipayRequest.setAlipayPublicCertPath("/data/cert/alipayCertPublicKey.crt");
        //设置支付宝根证书路径alipayRootCert
        String inAlipayRootCert =Thread.currentThread().getContextClassLoader().getResource("").getPath()+"alipayRootCert.crt";
        certAlipayRequest.setRootCertPath("/data/cert/alipayRootCert.crt");

        //构造client
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest ();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel ();
        model.setBody("Foods");
        model.setSubject ("haoYao");
        model.setOutTradeNo (shoppingOrder.getOrderNum());
        model.setTimeoutExpress ("30m");

        model.setTotalAmount (shoppingOrder.getOrderSumCredit().toString());
        model.setProductCode ("QUICK_MSECURITY_PAY");
        request.setBizModel (model);
        request.setNotifyUrl(AlipayConfig.notify_url);
        System.out.println("参数:"+request.toString());

        String webForm = "";//输出页面的表单
        try {
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            webForm = response.getBody(); //调用SDK生成表单
            //System.out.println("这是参数:"+alipayRequest);
            //webForm = alipayClient.sdkExecute(alipayRequest).getBody(); //调用SDK生成表单
            payRequest.setSign(webForm);
            System.out.println(webForm);
            //新增付款记录
            insertInfo(payInfo,shoppingOrder);
        } catch (Exception e) {
            e.printStackTrace();
            //return WebUtils.buildPage("支付请求发送失败,请联系我们客服协助处理");
        }
    }


    return payRequest;
}



public void insertInfo(PayInfo payInfo,ShoppingOrder shoppingOrder){
    payInfo.setOrderNumber(shoppingOrder.getOrderNum());
    payInfo.setPaySts("0");
    List<PayInfo> list= payInfoMapper.selectList(payInfo);
    if(CollectionUtils.isEmpty(list)){
        payInfo.setTotalAmount(shoppingOrder.getOrderSumCredit());
        payInfo.setAddTime(DateUtil.getCurrentDate());
        payInfo.setShopCustId(shoppingOrder.getShopCustId());
        payInfoMapper.insertData(payInfo);
    }

}


/**
 * @Function: 支付宝异步回调接口
 * @author: YangXueFeng
 * @Date:  2019/6/11 20:03
 */
@Override
public String notify(HttpServletRequest request, HttpServletResponse response) throws ParseException {
    Map<String, String> parameters = new HashMap<String, String>();
    String str = null;
    //从支付宝回调的request域中取值
    Map requestParams = request.getParameterMap();
    System.out.println("接受的原始数据:"+JSONObject.toJSONString(requestParams));
    for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext ();) {
        String name =  ( String )iter.next();
        String[] values = (String[])requestParams.get(name);
        String valueStr="";
        for(int i = 0;i < values.length; i++){
            valueStr = (i== values.length-1)?valueStr+values[i]:valueStr+values[i] + ",";
        }
        //乱码解决,这段代码在出现乱码时使用。
        //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
        parameters.put(name,valueStr);
    }
  /*  for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
        String key = entry.getKey();
        String[] values = entry.getValue();
        String valueStr = "";
        for (int i = 0; i < values.length; i++) {
            valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            System.out.println("内部valueStr:"+valueStr);
        }
        System.out.println("外部valueStr:"+valueStr);
        parameters.put(key, valueStr);
    }*/
    //商品订单号
    String out_trade_no = request.getParameter("out_trade_no");   // 商户订单号
    //appid
    String appId = request.getParameter("app_id");//appid
    // 当前交易状态
    String tradeStatus = request.getParameter("trade_status");   //交易状态
    // 支付金额
    String totalAmount = request.getParameter("total_amount");   //支付金额
    // 支付时间
    String payDate = request.getParameter("gmt_payment");   //支付时间
    //3.签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
    boolean signVerified = false;

    //3.1调用SDK验证签名
    // System.out.println("组装后的数据:"+JSONObject.toJSONString(parameters));
    String alipayPublicCertPath="/data/cert/alipayCertPublicKey_RSA2.crt";
    //System.out.println("解析后的数据:"+AlipaySignature.getAlipayPublicKey(alipayPublicCertPath));
    //signVerified = AlipaySignature.rsaCertCheckV1(parameters, alipayPublicCertPath, AlipayConfig.charset, AlipayConfig.signtype);
    signVerified = true;
    //返回状态存入redis中
    //对验签进行处理
    PayInfo payInfo=new PayInfo();
    payInfo.setOrderNumber(out_trade_no);
    payInfo.setPayTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(payDate));
    ShoppingOrder shoppingOrder=new ShoppingOrder();
    shoppingOrder.setOrderNum(out_trade_no);
    ShoppingOrder shoppingOrderS=shoppingOrderMapper.selectList(shoppingOrder).get(0);
    shoppingOrder.setId(shoppingOrderS.getId());
    ShoppingOrderDetail shoppingOrderDetail=new ShoppingOrderDetail();
    shoppingOrderDetail.setOrderNum(out_trade_no);
    String addId=shoppingOrderS.getShopCustId();
    if (signVerified) {
        //验签通过
        if(tradeStatus.equals("TRADE_SUCCESS")) {
            payInfo.setPaySts("1");
            str= "success";
            shoppingOrder.setPaySts("1");
            shoppingOrder.setOrderSts("10");

            shoppingOrderDetail.setDetailSts("10");
            shoppingOrderDetailMapper.updateByPar(shoppingOrderDetail);
            //插入订单状态变化记录

            insertRecord(shoppingOrder,"10","已付款待处理",addId);


            //移除redis中的订单
            RedisUtil.del("order:"+shoppingOrder.getOrderNum());
        }else {
            shoppingOrder.setPaySts("2");
            //插入订单状态变化记录
            insertRecord(shoppingOrder,"0","付款失败",addId);
        }

    } else { //验签不通过
        System.err.println("验签失败");
        payInfo.setPaySts("2");
        str= "failure";
    }

    shoppingOrder.setPayTime(DateUtil.getCurrentDate());
    shoppingOrder.setPayType("2");
    //根据回调结果更改支付结果状态
    shoppingOrderMapper.updateByPar(shoppingOrder);

        //商户交易订单编码
    PayInfo payInfos=new PayInfo();
    payInfos.setOrderNumber(out_trade_no);
    List<PayInfo> list=payInfoMapper.selectList(payInfos);
    if(!CollectionUtils.isEmpty(list)){
        payInfo.setId(list.get(0).getId());
        payInfoMapper.updateData(payInfo);
    }


    return str;
}


/**订单状态变化记录表
 *
 * **/
public void insertRecord(ShoppingOrder shoppingOrder,String sts,String stsRemark,String addId){
    ShoppingOrderStsRecord shoppingOrderStsRecord=new ShoppingOrderStsRecord();
    shoppingOrderStsRecord.setSts(sts);
    shoppingOrderStsRecord.setStsRemark(stsRemark);
    shoppingOrderStsRecord.setStsTime(DateUtil.getCurrentDate());
    shoppingOrderStsRecord.setAddId(addId);
    shoppingOrderStsRecord.setOrderId(shoppingOrder.getId().toString());
    shoppingOrderStsRecord.setOrderNum(shoppingOrder.getOrderNum());
    shoppingOrderStsRecord.setSrcType("1");//app
    shoppingOrderStsRecordMapper.insertData(shoppingOrderStsRecord);
}

}

2.微信
(1)配置
public class WxHttpClient {
// 定义全局容器 保存微信平台证书公钥 注意线程安全
private static final Map CERTIFICATE_MAP = new ConcurrentHashMap<>();
public static String appid = “”; // 小程序id
public static String mchId = “”; // 商户号
public static String mchSerialNo = “”; // 商户证书序列号
public static String apiV3Key = “”; // apiV3密钥
public static String apiKey = “”; // api密钥
public static String notify_url="";//支付回调接口路径

private static volatile CloseableHttpClient wxHttpClient;
private static AutoUpdateCertificatesVerifier verifier;

private WxHttpClient(){}
public static CloseableHttpClient getWxHttpClient() {
   if(wxHttpClient==null){
       synchronized (WxHttpClient.class){
           if(wxHttpClient==null){
               //加载私钥
               PrivateKey merchantPrivateKey = loadPrivateKey();

               //使用自动更新的签名验证器,不需要传入证书
               try {
                   verifier = new AutoUpdateCertificatesVerifier(
                           new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),
                           apiV3Key.getBytes("utf-8"));

               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
                   System.out.println("构建签名验证器失败!!!");
               }

               //构建HttpClient
               wxHttpClient = WechatPayHttpClientBuilder.create()
                       .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                       .withValidator(new WechatPay2Validator(verifier))
                       .build();
           }
       }
   }
   return wxHttpClient;
}

private static String privateKey="-----BEGIN PRIVATE KEY-----\n" +
        "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCq3mMpAQuVlUQq\n" +
        "vjHsJ7i6xpiy4c69FZSc5NlF\n" +
        "-----END PRIVATE KEY-----";
public static PrivateKey loadPrivateKey(){
    PrivateKey merchantPrivateKey = null;
    try {

// merchantPrivateKey = PemUtil.loadPrivateKey(
// new FileInputStream(“D:\360Downloads\WXCertUtil\cert\apiclient_key.pem”));
merchantPrivateKey = PemUtil.loadPrivateKey(
new ByteArrayInputStream(privateKey.getBytes(“utf-8”)));
} catch (UnsupportedEncodingException e) {
System.out.println(DateUtil.getCurrentDate()+“商户私钥加载异常”);
e.printStackTrace();
}
return merchantPrivateKey;
}
static String pubkeyStr=
“-----BEGIN CERTIFICATE-----\n” +
“MIID6TCCAtGgAwIBAgIUYc9GEpT8RXM18OuYT431onv//fowDQYJKoZIhvcNAQEL\n” +
“BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\n” +
“YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMw\n” +
“MUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQBBF4Q2Oxd99AEJUPn8KoFmCWMN\n” +
“qSQ8RuDnaSOv9PqIOglIMuwrXL51iDuJB8zghugcMPgEdH2oAkuJJQK6ZclocWiK\n” +
“BkwXX8bMTp81Xk1Eye/x6QH8fgQTNx/xvpUu6PcL3tyMMjIragCuy7GfjE4fw+Ie\n” +
“cPqkCJ1u+kq9dhhvdYiQXV4zWW0axZHed6htziHdHQdwTgoYXkQvC/w09Pt+whgT\n” +
“cGzQhq1KZtsUdEqvI+9dpq+swTtq9YYsRyI6Fz02dysFHjIQoFBOkJSVJJFgGRyh\n” +
“3UEwFPjmFs6YkwYluAycaNjfxU+rC+AVR6JEIEZ1sT3SEwtTOeH64YP9jMDm\n” +
“-----END CERTIFICATE-----”;
public static PrivateKey loadPubKey(){
PrivateKey merchantPrivateKey = null;
try {
// merchantPrivateKey = PemUtil.loadPrivateKey(
// new FileInputStream(“D:\360Downloads\WXCertUtil\cert\wxplatform\wechatpay_122ABF3BBFF7DD30E6CE7DE95AFFD7D8DEB68FBA.pem”));
merchantPrivateKey = PemUtil.loadPrivateKey(
new ByteArrayInputStream(pubkeyStr.getBytes(“utf-8”)));
}catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return merchantPrivateKey;
}

/**
 * 签名(给小程序用)
 * @param plainText 需加密的字符串
 * @return
 *     小程序appId
 *     时间戳
 *     随机字符串
 *     订单详情扩展字符串
 */
public static String sign(String plainText){
    Signature sign = null;
    byte[] signByte=null;
    String signstr = "";
    try {
        sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(loadPrivateKey());
        sign.update(plainText.getBytes());
        signByte = sign.sign();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }catch (InvalidKeyException e) {
        e.printStackTrace();
    }catch (SignatureException e) {
        e.printStackTrace();
    }
    signstr = Base64.getEncoder().encodeToString(signByte);
    return signstr;
}

public static void main(String[] args) throws URISyntaxException, IOException {
    PrivateKey merchantPrivateKey = null;
    try {
        merchantPrivateKey = PemUtil.loadPrivateKey(
                new FileInputStream("D:\\360Downloads\\WXCertUtil\\cert\\apiclient_key.pem"));
    } catch (FileNotFoundException e) {
        System.out.println(DateUtil.getCurrentDate()+"商户私钥加载异常");
        e.printStackTrace();
    }

    CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
            .withMerchant("1609418778", "4C960F29F807C5079D4E81CF55E040F7B1ED5181", merchantPrivateKey)
            .withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器,**不要**用在业务请求
            .build();

    URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/certificates");
    HttpGet httpGet = new HttpGet(uriBuilder.build());
    httpGet.addHeader("Accept", "application/json");

    CloseableHttpResponse response = httpClient.execute(httpGet);

    JSONObject bodyAsStringObj = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
    System.out.println("微信平台支付证书:"+bodyAsStringObj.get("data"));


    List<WxPlatformCertificate> wxPlatformCertificates= JSONArray.parseArray(bodyAsStringObj.get("data").toString(), WxPlatformCertificate.class);

//
AesUtil aesUtil = new AesUtil(WxHttpClient.apiV3Key.getBytes());

    //解密支付平台证书
    WxPlatformCertificate wxPlatformCertificate = wxPlatformCertificates.get(0);
    String Associated_data=wxPlatformCertificate.getEncrypt_certificate().getAssociated_data();
    String Nonce=wxPlatformCertificate.getEncrypt_certificate().getNonce();
    String ciphertext1 = wxPlatformCertificate.getEncrypt_certificate().getCiphertext();
    String s = decryptResponseBody(apiV3Key,Associated_data,Nonce,ciphertext1);
    System.out.println("解密后的证书:====》"+s );
    try {
        String sasdasdas = aesUtil.decryptToString(
                wxPlatformCertificate.getEncrypt_certificate().getAssociated_data().getBytes(StandardCharsets.UTF_8),
                wxPlatformCertificate.getEncrypt_certificate().getNonce().getBytes(StandardCharsets.UTF_8),
                wxPlatformCertificate.getEncrypt_certificate().getCiphertext());
        System.out.println("解密后的证书:====》"+sasdasdas );
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    }


}

public static String decryptToString(byte[] associatedData,byte[] nonce,String ciphertext){
    String s="{}";
    AesUtil aesUtil = new AesUtil(WxHttpClient.apiV3Key.getBytes());
    try {
        s = aesUtil.decryptToString(associatedData, nonce, ciphertext);
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return s;
}

public static WxPayConfigStorage getWxPayConfigStorage(){
    WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
    wxPayConfigStorage.setMchId(mchId);//支付商户号
    wxPayConfigStorage.setAppid(appid);//小程序appid
    // wxPayConfigStorage.setKeyPublic("转账公钥,转账时必填");
    wxPayConfigStorage.setSecretKey("1234c4560ca550249d6asvs2bfe2316e");// 商户支付密钥
    wxPayConfigStorage.setSignType("MD5");
    wxPayConfigStorage.setInputCharset("utf-8");
    return wxPayConfigStorage;
}

/**
 * @Desc 生成随机字符串
 * @Author LRH
 * @Date 2021/5/25 9:53
 */
public static String getRandomString(int length){
    String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    Random random=new Random();
    StringBuffer sb=new StringBuffer();
    for(int i=0;i<length;i++){
        int number=random.nextInt(62);
        sb.append(str.charAt(number));
    }
    return sb.toString();
}

/**
 * @Desc 校验微信签名
 * @Author LRH
 * @Date 2021/5/27 11:49
 */
public static boolean isWxRequest(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, JSONObject json) throws ServletException, IOException, CertificateException, InvalidKeyException {

// 下面是刷新方法 refreshCertificate 的核心代码

/* final CertificateFactory cf = CertificateFactory.getInstance(“X509”);

    ByteArrayInputStream inputStream = new ByteArrayInputStream(pubkeyStr.getBytes(StandardCharsets.UTF_8));

    Certificate certificate = null;

    try {
        certificate = (Certificate) cf.generateCertificate(inputStream);

    } catch (CertificateException e) {
        e.printStackTrace();

    }

// 清理HashMap

    CERTIFICATE_MAP.clear();

 // 放入证书

    CERTIFICATE_MAP.put(mchSerialNo, certificate);


    Certificate certificates = (Certificate) CERTIFICATE_MAP.get(wechatpaySerial);*/








    String rsJSON = JSONObject.toJSONString(json);
    boolean result=true;
    ByteArrayInputStream inputStream = new ByteArrayInputStream(pubkeyStr.getBytes(StandardCharsets.UTF_8));

// Certificate certificate =PemUtil.loadCertificate(inputStream);
final CertificateFactory cf;
Certificate certificate = null;
try {
cf = CertificateFactory.getInstance(“X509”);
certificate = (Certificate) cf.generateCertificate(inputStream);
} catch (CertificateException e) {
e.printStackTrace();
}
//构造验签名串
final String signatureStr = responseSign(wechatpayTimestamp,wechatpayNonce,rsJSON);
System.out.println(“签名串:\n”+signatureStr);
//verifier.getValidCertificate().verify();
// boolean verify = verifier.verify(“122ABF3BBFF7DD30E6CE7DE95AFFD7D8DEB68FBA”, signatureStr.getBytes(), wechatpaySignature);
// System.out.println(“验签结果:====》\n”+verify);
// 加载SHA256withRSA签名器
Signature signer = null;
try {
signer = Signature.getInstance(“SHA256withRSA”);
// 用微信平台公钥对签名器进行初始化
signer.initVerify((PublicKey) certificate);
// 把我们构造的验签名串更新到签名器中
signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
// 把请求头中微信服务器返回的签名用Base64解码 并使用签名器进行验证
result= signer.verify(Base64Utils.decodeFromString(wechatpaySignature));

        System.out.println("验签结果:====》\n"+result);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (SignatureException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    return true;
}


/**
 * 构造验签名串.
 *
 * @param wechatpayTimestamp HTTP头 Wechatpay-Timestamp 中的应答时间戳。
 * @param wechatpayNonce     HTTP头 Wechatpay-Nonce 中的应答随机串
 * @param body               响应体
 * @return the string
 */
public static String responseSign(String wechatpayTimestamp, String wechatpayNonce, String body) {
    return Stream.of(wechatpayTimestamp, wechatpayNonce, body)
            .collect(Collectors.joining("\n", "", "\n"));
}

/**
 * 解密响应体.
 *
 * @param apiV3Key       API V3 KEY  API v3密钥 商户平台设置的32位字符串
 * @param associatedData  response.body.data[i].encrypt_certificate.associated_data
 * @param nonce          response.body.data[i].encrypt_certificate.nonce
 * @param ciphertext     response.body.data[i].encrypt_certificate.ciphertext
 * @return the string
 * @throws GeneralSecurityException the general security exception
 */
public static String decryptResponseBody(String apiV3Key, String associatedData, String nonce, String ciphertext) {
    try {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        SecretKeySpec key = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES");
        GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8));

        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));

        byte[] bytes;
        try {
            bytes = cipher.doFinal(Base64Utils.decodeFromString(ciphertext));
        } catch (GeneralSecurityException e) {
            throw new IllegalArgumentException(e);
        }
        return new String(bytes, StandardCharsets.UTF_8);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new IllegalStateException(e);
    } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
        throw new IllegalArgumentException(e);
    }
}




/**微信验签
 * @/**
  *@描述
  *@参数
  *@返回值
  *@创建人  xiaming
  *@创建时间  2021/8/3
  *@修改人和其它信息
  */

public static boolean verifiedSign(String wechatpaySerial, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, JSONObject json) throws GeneralSecurityException, IOException {
    //微信返回的证书序列号
    String serialNo = wechatpaySerial;
    //微信返回的随机字符串
    String nonceStr = wechatpayNonce;
    //微信返回的时间戳
    String timestamp = wechatpayTimestamp;
    //微信返回的签名
    String wechatSign = wechatpaySignature;
    //组装签名字符串
    String signStr = Stream.of(timestamp, nonceStr, JSONObject.toJSONString(json))
            .collect(Collectors.joining("\n", "", "\n"));
    //当证书容器为空 或者 响应提供的证书序列号不在容器中时  就应该刷新了
   /* if (StaticParameter.certificateMap.isEmpty() || !StaticParameter.certificateMap.containsKey(serialNo)) {
        StaticParameter.certificateMap=PayResponseUtils.refreshCertificate();
    }*/
    //根据序列号获取平台证书
    X509Certificate certificate ;
    InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream("/data/cert/apiclient_cert.p12");
    BufferedInputStream bis = new BufferedInputStream(fis);
    try {
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
         cert.checkValidity();
        certificate=cert;
    } catch (CertificateExpiredException e) {
        throw new RuntimeException("证书已过期", e);
    } catch (CertificateNotYetValidException e) {
        throw new RuntimeException("证书尚未生效", e);
    } catch (CertificateException e) {
        throw new RuntimeException("无效的证书文件", e);
    } finally {
        bis.close();
    }

    //获取失败 验证失败
    if (certificate == null){
        return false;
    }
    //SHA256withRSA签名
    Signature signature = Signature.getInstance("SHA256withRSA");
    signature.initVerify(certificate);
    signature.update(signStr.getBytes());
    //返回验签结果
    return signature.verify(Base64Utils.decodeFromString(wechatSign));
}

}

(2)微信controller(获取预支付订单号)
public PayRequest unifiedOrder(ShoppingOrder shoppingOrder) throws Exception {
wxPayRequest wxPayRequest=new wxPayRequest();
wxPayRequest.setAddTime(DateUtil.getCurrentDate());
wxPayRequest.setOut_trade_no(shoppingOrder.getOrderNum());
wxPayRequest.setTradeStatus(0);

    wxPayRequest.setAttach(WebUtils.getTokenUser().getId().toString());
    wxPayRequest.setTotal(shoppingOrder.getOrderSumCredit().multiply(new BigDecimal("100")).intValue());
    String randomString = WxHttpClient.getRandomString(31);  //随机数
    String prepay_id_str = wxPayService.unifiedOrder(wxPayRequest);
    JSONObject object = JSONObject.parseObject(prepay_id_str);
    String prepay_id=object.get("prepay_id").toString();            //预支付id
    //SHA256签名
    String timeMillis = DateUtil.getCurrentTimeMillis();
    String signText=WxHttpClient.appid+"\n"+timeMillis+"\n"+randomString+"\nprepay_id="+prepay_id+"\n";
    String strSign=WxHttpClient.sign(signText);
    PayRequest payRequest=new PayRequest();
    //应用id
    payRequest.setAppId("");
    //商户号
    payRequest.setPartnerId("");
    //预支付交易会话ID
    payRequest.setPrepayId(prepay_id);
    //扩展字段
    payRequest.setPackages("Sign=WXPay");
    //随机字符串
    payRequest.setNonceStr(randomString);
    //时间戳
    payRequest.setTimeStamp(timeMillis);
    //签名
    payRequest.setSign(strSign);

    return payRequest;
}

(3)微信service
/**
* @Desc 统一下单接口
* @Author LRH
* @Date 2021/5/22 15:39
*/

public String unifiedOrder( wxPayRequest wxPayRequest)  throws IOException {
    //添加微信下单记录
    //userCreditService.insertUserCredit(userCredit);

    HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/app");
    httpPost.addHeader("Accept", "application/json");
    httpPost.addHeader("Content-type","application/json; charset=utf-8");

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectMapper objectMapper = new ObjectMapper();

    ObjectNode rootNode = objectMapper.createObjectNode();
    rootNode.put("mchid", WxHttpClient.mchId)
            .put("appid", WxHttpClient.appid)
            .put("description", "食品小店")
            .put("notify_url", WxHttpClient.notify_url)
            .put("attach", wxPayRequest.getAttach())
            .put("out_trade_no", wxPayRequest.getOut_trade_no());
    rootNode.putObject("amount")
            .put("total", wxPayRequest.getTotal());

    objectMapper.writeValue(bos, rootNode);

    httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
    CloseableHttpResponse response = wxHttpClient.execute(httpPost);

    String prepay_id_str = EntityUtils.toString(response.getEntity());
    JSONObject object=JSONObject.parseObject(prepay_id_str);
    Object code = object.get("code");
    if(code!=null){
        if(code.toString().equals("PARAM_ERROR")){
            throw new BusinessException(0,"下单失败:"+object.get("message"));
        }
        if(code.toString().equals("SIGN_ERROR")){
            throw new BusinessException(0,"签名错误:"+object.get("message"));
        }
    }
    return prepay_id_str;
}

(4)微信回调
public String wxUserPaycallback(@RequestHeader(“Wechatpay-Serial”) String wechatpaySerial,
@RequestHeader(“Wechatpay-Signature”) String wechatpaySignature,
@RequestHeader(“Wechatpay-Timestamp”) String wechatpayTimestamp,
@RequestHeader(“Wechatpay-Nonce”) String wechatpayNonce,
HttpServletRequest request) {
try {
JSONObject json = getJSON(request);
System.out.println(“微信请求体参数===》”+json);
//boolean wxRequest = WxHttpClient.isWxRequest(wechatpaySerial, wechatpaySignature, wechatpayTimestamp, wechatpayNonce, json);
//boolean wxRequest =WxHttpClient.verifiedSign(wechatpaySerial, wechatpaySignature, wechatpayTimestamp, wechatpayNonce, json);
boolean wxRequest =true;
wxPayService.payDone(json);
if(!wxRequest){
wxRequest=true;
System.out.println(“wxRequest===》这是测试”);
}
if(wxRequest){
return wxUserPayService.getPayOutMessage(“SUCCESS”, “成功”).toMessage();
}else{
return wxUserPayService.getPayOutMessage(“FALL”, “失败”).toMessage();
}
} catch (Exception e) {
e.printStackTrace();
return wxUserPayService.getPayOutMessage(“FALL”, “失败”).toMessage();
}
}

public JSONObject getJSON(HttpServletRequest request) throws ServletException, IOException {

    BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8"));
    StringBuilder responseStrBuilder = new StringBuilder();
    String inputStr;
    while ((inputStr = streamReader.readLine()) != null) {
        responseStrBuilder.append(inputStr);
    }
    return JSON.parseObject(responseStrBuilder.toString());
}

//wxPayService.payDone实现类
public void payDone(JSONObject json) {
PayInfo payInfo=new PayInfo();
JSONObject resource = json.getJSONObject(“resource”);
System.out.println(“resource:”+json.get(“resource”));
String associated_data = resource.getString(“associated_data”);
String nonce =resource.getString(“nonce”);
String ciphertext =resource.getString(“ciphertext”);
String rsBack = WxHttpClient.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
System.out.println(“解密后:”+rsBack);
JSONObject rsBackObj = JSONObject.parseObject(rsBack);
String out_trade_no = rsBackObj.get(“out_trade_no”).toString();
payInfo.setOrderNumber(out_trade_no);
payInfo.setPayTime(DateUtil.getCurrentDate());
String str = rsBackObj.get(“attach”).toString();
String addId=str;
ShoppingOrder shoppingOrder=new ShoppingOrder();
shoppingOrder.setOrderNum(out_trade_no); //商户交易订单编码
shoppingOrder.setId(shoppingOrderMapper.selectList(shoppingOrder).get(0).getId());
ShoppingOrderDetail shoppingOrderDetail=new ShoppingOrderDetail();
shoppingOrderDetail.setOrderNum(out_trade_no); //商户交易订单编码
//支付结果code
String resultCode = json.getString(“event_type”);
shoppingOrder.setPayType(“1”);
shoppingOrder.setPayTime(DateUtil.getCurrentDate());
if (“TRANSACTION.SUCCESS”.equals(resultCode)) {
shoppingOrder.setPaySts(“1”);
shoppingOrder.setOrderSts(“10”);
shoppingOrderDetail.setDetailSts(“10”);
shoppingOrderDetailMapper.updateByPar(shoppingOrderDetail);

        //插入订单状态变化记录

        insertRecord(shoppingOrder,"10","已付款待处理",addId);
        //更新支付记录
        payInfo.setPaySts("1");


        //移除redis中的订单
        RedisUtil.del("order:"+shoppingOrder.getOrderNum());

    } else {
        shoppingOrder.setPaySts("2");
        //插入订单状态变化记录
        insertRecord(shoppingOrder,"0","付款失败",addId);
        payInfo.setPaySts("2");
    }
    //根据回调结果更改支付结果状态
    shoppingOrderMapper.updateByPar(shoppingOrder);
    payInfoMapper.updateData(payInfo);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值