• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Java 接入微信支付API V3 接口开发案例

武飞扬头像
PandaXu123456789
帮助2

关于API v3

为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付API v3。

相较于之前的微信支付API,主要区别是:

  • 遵循统一的REST的设计风格
  • 使用JSON作为数据交互的格式,不再使用XML
  • 使用基于非对称密钥的SHA256-RSA的数字签名算法,不再使用MD5或HMAC-SHA256
  • 不再要求携带HTTPS客户端证书(仅需携带证书序列号)
  • 使用AES-256-GCM,对回调中的关键信息进行加密保护

最近接微信支付API v3接口,踩了一些坑,分享一下,帮助码友避免采坑,话不多少,直接上代码。

WeiXinPaySignUtils

  1.  
    public class WeiXinPaySignUtils {
  2.  
     
  3.  
    /**
  4.  
    * 生成组装请求头
  5.  
    *
  6.  
    * @param method 请求方式
  7.  
    * @param url 请求地址
  8.  
    * @param mercId 商户ID
  9.  
    * @param serial_no 证书序列号
  10.  
    * @param privateKeyFilePath 私钥路径
  11.  
    * @param body 请求体
  12.  
    * @return 组装请求的数据
  13.  
    * @throws Exception
  14.  
    */
  15.  
    public static String getToken(String method, HttpUrl url, String mercId,
  16.  
    String serial_no, String privateKeyFilePath, String body) throws Exception {
  17.  
    String nonceStr = UUID.randomUUID().toString().replace("-", "");
  18.  
    long timestamp = System.currentTimeMillis() / 1000;
  19.  
    String message = buildMessage(method, url, timestamp, nonceStr, body);
  20.  
    String signature = sign(message.getBytes("UTF-8"), privateKeyFilePath);
  21.  
    return "mchid=\"" mercId "\","
  22.  
    "nonce_str=\"" nonceStr "\","
  23.  
    "timestamp=\"" timestamp "\","
  24.  
    "serial_no=\"" serial_no "\","
  25.  
    "signature=\"" signature "\"";
  26.  
    }
  27.  
     
  28.  
     
  29.  
    /**
  30.  
    * 生成签名
  31.  
    *
  32.  
    * @param message 请求体
  33.  
    * @param privateKeyFilePath 私钥的路径
  34.  
    * @return 生成base64位签名信息
  35.  
    * @throws Exception
  36.  
    */
  37.  
    public static String sign(byte[] message, String privateKeyFilePath) throws Exception {
  38.  
    Signature sign = Signature.getInstance("SHA256withRSA");
  39.  
    sign.initSign(getPrivateKey(privateKeyFilePath));
  40.  
    sign.update(message);
  41.  
    return Base64.getEncoder().encodeToString(sign.sign());
  42.  
    }
  43.  
     
  44.  
    /**
  45.  
    * 组装签名加载
  46.  
    *
  47.  
    * @param method 请求方式
  48.  
    * @param url 请求地址
  49.  
    * @param timestamp 请求时间
  50.  
    * @param nonceStr 请求随机字符串
  51.  
    * @param body 请求体
  52.  
    * @return 组装的字符串
  53.  
    */
  54.  
    public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
  55.  
    String canonicalUrl = url.encodedPath();
  56.  
    if (url.encodedQuery() != null) {
  57.  
    canonicalUrl = "?" url.encodedQuery();
  58.  
    }
  59.  
    return method "\n"
  60.  
    canonicalUrl "\n"
  61.  
    timestamp "\n"
  62.  
    nonceStr "\n"
  63.  
    body "\n";
  64.  
    }
  65.  
     
  66.  
    /**
  67.  
    * 获取私钥。
  68.  
    *
  69.  
    * @param filename 私钥文件路径 (required)
  70.  
    * @return 私钥对象
  71.  
    */
  72.  
    public static PrivateKey getPrivateKey(String filename) throws IOException {
  73.  
    String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");
  74.  
    try {
  75.  
    String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
  76.  
    .replace("-----END PRIVATE KEY-----", "")
  77.  
    .replaceAll("\\s ", "");
  78.  
    KeyFactory kf = KeyFactory.getInstance("RSA");
  79.  
    return kf.generatePrivate(
  80.  
    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
  81.  
    } catch (NoSuchAlgorithmException e) {
  82.  
    throw new RuntimeException("当前Java环境不支持RSA", e);
  83.  
    } catch (InvalidKeySpecException e) {
  84.  
    throw new RuntimeException("无效的密钥格式");
  85.  
    }
  86.  
    }
  87.  
     
  88.  
    /**
  89.  
    * 构造签名串
  90.  
    *
  91.  
    * @param signMessage 待签名的参数
  92.  
    * @return 构造后带待签名串
  93.  
    */
  94.  
    public static String buildSignMessage(ArrayList<String> signMessage) {
  95.  
    if (signMessage == null || signMessage.size() <= 0) {
  96.  
    return null;
  97.  
    }
  98.  
    StringBuilder sbf = new StringBuilder();
  99.  
    for (String str : signMessage) {
  100.  
    sbf.append(str).append("\n");
  101.  
    }
  102.  
    return sbf.toString();
  103.  
    }
  104.  
     
  105.  
    /**
  106.  
    * v3 支付异步通知验证签名
  107.  
    *
  108.  
    * @param body 异步通知密文
  109.  
    * @param key api 密钥
  110.  
    * @return 异步通知明文
  111.  
    * @throws Exception 异常信息
  112.  
    */
  113.  
    public static String verifyNotify(String body, String key) throws Exception {
  114.  
    // 获取平台证书序列号
  115.  
    cn.hutool.json.JSONObject resultObject = JSONUtil.parseObj(body);
  116.  
    cn.hutool.json.JSONObject resource = resultObject.getJSONObject("resource");
  117.  
    String cipherText = resource.getStr("ciphertext");
  118.  
    String nonceStr = resource.getStr("nonce");
  119.  
    String associatedData = resource.getStr("associated_data");
  120.  
    AesUtil aesUtil = new AesUtil(key.getBytes(StandardCharsets.UTF_8));
  121.  
    // 密文解密
  122.  
    return aesUtil.decryptToString(
  123.  
    associatedData.getBytes(StandardCharsets.UTF_8),
  124.  
    nonceStr.getBytes(StandardCharsets.UTF_8),
  125.  
    cipherText
  126.  
    );
  127.  
    }
  128.  
     
  129.  
    /**
  130.  
    * 处理返回对象
  131.  
    *
  132.  
    * @param request
  133.  
    * @return
  134.  
    */
  135.  
    public static String readData(HttpServletRequest request) {
  136.  
    BufferedReader br = null;
  137.  
    try {
  138.  
    StringBuilder result = new StringBuilder();
  139.  
    br = request.getReader();
  140.  
    for (String line; (line = br.readLine()) != null; ) {
  141.  
    if (result.length() > 0) {
  142.  
    result.append("\n");
  143.  
    }
  144.  
    result.append(line);
  145.  
    }
  146.  
    return result.toString();
  147.  
    } catch (IOException e) {
  148.  
    throw new RuntimeException(e);
  149.  
    } finally {
  150.  
    if (br != null) {
  151.  
    try {
  152.  
    br.close();
  153.  
    } catch (IOException e) {
  154.  
    e.printStackTrace();
  155.  
    }
  156.  
    }
  157.  
    }
  158.  
    }
  159.  
    }
学新通

AesUtil

  1.  
    public class AesUtil {
  2.  
    static final int KEY_LENGTH_BYTE = 32;
  3.  
    static final int TAG_LENGTH_BIT = 128;
  4.  
    private final byte[] aesKey;
  5.  
     
  6.  
    /**
  7.  
    * @param key APIv3 密钥
  8.  
    */
  9.  
    public AesUtil(byte[] key) {
  10.  
    if (key.length != KEY_LENGTH_BYTE) {
  11.  
    throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
  12.  
    }
  13.  
    this.aesKey = key;
  14.  
    }
  15.  
     
  16.  
    /**
  17.  
    * 证书和回调报文解密
  18.  
    *
  19.  
    * @param associatedData associated_data
  20.  
    * @param nonce nonce
  21.  
    * @param cipherText ciphertext
  22.  
    * @return {String} 平台证书明文
  23.  
    * @throws GeneralSecurityException 异常
  24.  
    */
  25.  
    public String decryptToString(byte[] associatedData, byte[] nonce, String cipherText) throws GeneralSecurityException {
  26.  
    try {
  27.  
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
  28.  
    SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
  29.  
    GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
  30.  
    cipher.init(Cipher.DECRYPT_MODE, key, spec);
  31.  
    cipher.updateAAD(associatedData);
  32.  
    return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)), StandardCharsets.UTF_8);
  33.  
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
  34.  
    throw new IllegalStateException(e);
  35.  
    } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
  36.  
    throw new IllegalArgumentException(e);
  37.  
    }
  38.  
    }
  39.  
     
  40.  
    /**
  41.  
    * 敏感信息加密
  42.  
    *
  43.  
    * @param message
  44.  
    * @param certificate
  45.  
    * @return
  46.  
    * @throws IllegalBlockSizeException
  47.  
    * @throws IOException
  48.  
    */
  49.  
    public static String rsaEncryptOAEP(String message, X509Certificate certificate)
  50.  
    throws IllegalBlockSizeException, IOException {
  51.  
    try {
  52.  
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
  53.  
    cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
  54.  
     
  55.  
    byte[] data = message.getBytes("utf-8");
  56.  
    byte[] cipherdata = cipher.doFinal(data);
  57.  
    return Base64.getEncoder().encodeToString(cipherdata);
  58.  
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
  59.  
    throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
  60.  
    } catch (InvalidKeyException e) {
  61.  
    throw new IllegalArgumentException("无效的证书", e);
  62.  
    } catch (IllegalBlockSizeException | BadPaddingException e) {
  63.  
    throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
  64.  
    }
  65.  
    }
  66.  
     
  67.  
    /**
  68.  
    * 敏感信息解密
  69.  
    *
  70.  
    * @param ciphertext
  71.  
    * @param privateKey
  72.  
    * @return
  73.  
    * @throws BadPaddingException
  74.  
    * @throws IOException
  75.  
    */
  76.  
    public static String rsaDecryptOAEP(String ciphertext, PrivateKey privateKey)
  77.  
    throws BadPaddingException, IOException {
  78.  
    try {
  79.  
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
  80.  
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
  81.  
     
  82.  
    byte[] data = Base64.getDecoder().decode(ciphertext);
  83.  
    return new String(cipher.doFinal(data), "utf-8");
  84.  
    } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
  85.  
    throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
  86.  
    } catch (InvalidKeyException e) {
  87.  
    throw new IllegalArgumentException("无效的私钥", e);
  88.  
    } catch (BadPaddingException | IllegalBlockSizeException e) {
  89.  
    throw new BadPaddingException("解密失败");
  90.  
    }
  91.  
    }
  92.  
     
  93.  
    }
学新通

WeiXinV3FundinFacade

下单:

  1.  
    @PostMapping("/pay")
  2.  
    public ResultWrapper<Map<String,Object>> fundin(@RequestBody String request){
  3.  
    logger.info("PayChannelOrder->Channel微信V3支付渠道请求参数:" request);
  4.  
    ChannelFundResult result = new ChannelFundResult();
  5.  
    ChannelFundRequest req = JSON.parseObject(request, ChannelFundRequest.class);
  6.  
    logger.info("PayChannelOrder->Channel微信V3支付渠道请求参数转换对象:" req);
  7.  
    Properties properties = propertyHelper.getProperties(req.getFundChannelCode());
  8.  
    //判断mock开关是否打开,是否要返回mock数据
  9.  
    String mock_switch = properties.getProperty(WXPAYFundChannelKey.MOCK_SWITCH);
  10.  
    if("true".equals(mock_switch)){//开关开启返回mock数据
  11.  
    result.setApiType(req.getApiType());
  12.  
    result.setRealAmount(req.getAmount());
  13.  
    result.setInstOrderNo(req.getInstOrderNo());
  14.  
    result.setProcessTime(new Date());
  15.  
    result = MockResultData.mockResule(result);
  16.  
    logger.info("注意这是mock数据!");
  17.  
    return ResultWrapper.ok().putData(result);
  18.  
    }
  19.  
    try {
  20.  
    H5V3WxPayVO h5V3WxPayVO = new H5V3WxPayVO();
  21.  
    String appId = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_APPID);
  22.  
    h5V3WxPayVO.setAppid(appId);
  23.  
    logger.info("【微信V3支付配置】->【微信appID】:" appId);
  24.  
    String mchId = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_MCHID);
  25.  
    h5V3WxPayVO.setMchid(mchId);
  26.  
    logger.info("【微信V3支付配置】->【微信商户ID】:" mchId);
  27.  
    String notifyUrl = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_NOTIFYURL);
  28.  
    h5V3WxPayVO.setNotify_url(notifyUrl);
  29.  
    logger.info("【微信V3支付配置】->【异步通知URL】:" notifyUrl);
  30.  
    String description = req.getExtension().get("description");
  31.  
    h5V3WxPayVO.setDescription(description);
  32.  
    logger.info("【微信V3支付配置】->【商品描述】:" description);
  33.  
    String outTradeNo = req.getInstOrderNo();
  34.  
    h5V3WxPayVO.setOut_trade_no(outTradeNo);
  35.  
    logger.info("【微信V3支付配置】->【商户订单号】:" outTradeNo);
  36.  
    String attach = req.getExtension().get("attach");
  37.  
    if(StringUtils.isNotBlank(attach)){
  38.  
    h5V3WxPayVO.setAttach(attach);
  39.  
    }
  40.  
     
  41.  
    AmountVO amount = new AmountVO();
  42.  
    amount.setTotal(MoneyUtil.Yuan2Fen(req.getAmount().doubleValue()));
  43.  
    amount.setCurrency("CNY");
  44.  
    h5V3WxPayVO.setAmount(amount);
  45.  
    PayerVO payer = new PayerVO();
  46.  
    String openId = req.getExtension().get("openId");
  47.  
    payer.setOpenid(openId);
  48.  
    h5V3WxPayVO.setPayer(payer);
  49.  
    String isDetail = req.getExtension().get("isDetail");
  50.  
    if("true".equals(isDetail)){
  51.  
    DetailVO detail = new DetailVO();
  52.  
    int costPrice = MoneyUtil.Yuan2Fen(req.getAmount().doubleValue());
  53.  
    detail.setCostprice(costPrice);
  54.  
    String invoiceId = req.getExtension().get("invoiceId");
  55.  
    detail.setInvoiceId(invoiceId);
  56.  
    String goodsDetailJson = req.getExtension().get("goodsDetail");
  57.  
    List<GoodsDetailVO> goodsDetailVOList = JSON.parseArray(goodsDetailJson,GoodsDetailVO.class);
  58.  
    detail.setGoods_detail(goodsDetailVOList);
  59.  
    h5V3WxPayVO.setDetail(detail);
  60.  
    }
  61.  
    SceneInfoVO sceneInfoVO = new SceneInfoVO();
  62.  
    String payerClientIp = req.getExtension().get("payerClientIp");
  63.  
    sceneInfoVO.setPayer_client_ip(payerClientIp);
  64.  
    String deviceId = req.getExtension().get("deviceId");
  65.  
    if(StringUtils.isNotBlank(deviceId)){
  66.  
    sceneInfoVO.setDevice_id(deviceId);
  67.  
    }
  68.  
    String storeInfoJson = req.getExtension().get("storeInfo");
  69.  
    if(StringUtils.isNotBlank(storeInfoJson)){
  70.  
    StoreInfoVO storeInfo = JSON.parseObject(storeInfoJson,StoreInfoVO.class);
  71.  
    sceneInfoVO.setStore_info(storeInfo);
  72.  
    h5V3WxPayVO.setScene_info(sceneInfoVO);
  73.  
    }
  74.  
    SettleInfoVO settleInfo = new SettleInfoVO();
  75.  
    String profitSharing = req.getExtension().get("profitSharing");
  76.  
    if("true".equals(profitSharing)){
  77.  
    settleInfo.setProfit_sharing(true);
  78.  
    }else{
  79.  
    settleInfo.setProfit_sharing(false);
  80.  
    }
  81.  
    h5V3WxPayVO.setSettle_info(settleInfo);
  82.  
    String jsonStr = JSON.toJSONString(h5V3WxPayVO);
  83.  
    logger.info("【微信V3支付】->请求参数JSON:{}",jsonStr);
  84.  
    // 发送请求
  85.  
    String url =properties.getProperty(WXPAYFundChannelKey.JSAPI_CREAT_URL);
  86.  
    logger.info("【微信V3支付配置】->【请求URL】:{}",url);
  87.  
    //创建httpclient对象
  88.  
    CloseableHttpClient client = HttpClients.createDefault();
  89.  
    //创建post方式请求对象
  90.  
    HttpPost httpPost = new HttpPost(url_prex url);
  91.  
    //装填参数
  92.  
    StringEntity s = new StringEntity(jsonStr, charset);
  93.  
    s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
  94.  
    "application/json"));
  95.  
    //设置参数到请求对象中
  96.  
    httpPost.setEntity(s);
  97.  
    String mchSerialNo = properties.getProperty(WXPAYFundChannelKey.MCH_SERIAL_NO);
  98.  
    String privateKeyFilePath = properties.getProperty(WXPAYFundChannelKey.PRIVATE_KEY_FILE_PATH);
  99.  
    String token = WeiXinPaySignUtils.getToken("POST", HttpUrl.parse(url_prex url), mchId, mchSerialNo, privateKeyFilePath, jsonStr);
  100.  
    //设置header信息
  101.  
    //指定报文头【Content-type】、【User-Agent】
  102.  
    httpPost.setHeader("Content-type", "application/json");
  103.  
    httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
  104.  
    httpPost.setHeader("Accept", "application/json");
  105.  
    httpPost.setHeader("Authorization",
  106.  
    "WECHATPAY2-SHA256-RSA2048 " token);
  107.  
    //执行请求操作,并拿到结果(同步阻塞)
  108.  
    CloseableHttpResponse response = client.execute(httpPost);
  109.  
    //获取结果实体
  110.  
    HttpEntity entity = response.getEntity();
  111.  
    String body = "";
  112.  
    if (entity != null) {
  113.  
    //按指定编码转换结果实体为String类型
  114.  
    body = EntityUtils.toString(entity, charset);
  115.  
    }
  116.  
    EntityUtils.consume(entity);
  117.  
    //释放链接
  118.  
    response.close();
  119.  
    String responseJson = JSONObject.fromObject(body).getString("prepay_id");
  120.  
    logger.info("【微信V3支付】->返回结果->prepay_id:{}",responseJson);
  121.  
    StatusLine statusLine = response.getStatusLine();
  122.  
    if(StringUtils.isBlank(responseJson)){
  123.  
    result.setApiResultCode(String.valueOf(statusLine.getStatusCode()));
  124.  
    result.setApiResultMessage(statusLine.getReasonPhrase());
  125.  
    result.setResultMessage(statusLine.getReasonPhrase());
  126.  
    result.setSuccess(false);
  127.  
    result.setRealAmount(req.getAmount());
  128.  
    result.setProcessTime(new Date());
  129.  
    result.setFundChannelCode(req.getFundChannelCode());
  130.  
    result.setApiType(FundChannelApiType.DEBIT);
  131.  
    result.setExtension("");
  132.  
    result.setInstOrderNo(req.getInstOrderNo());
  133.  
    logger.info("返回支付平台结果:" JSON.toJSONString(result));
  134.  
    return ResultWrapper.ok().putData(result);
  135.  
    }else{
  136.  
    //
  137.  
    JSONObject jsonObject = WxTuneUp(responseJson, appId, privateKeyFilePath);
  138.  
    result.setApiResultCode("0000");
  139.  
    result.setApiResultSubCode("SUCCESS");
  140.  
    result.setApiResultMessage("微信支付下单成功");
  141.  
    result.setResultMessage("微信支付下单成功");
  142.  
    result.setSuccess(true);
  143.  
    result.setRealAmount(req.getAmount());
  144.  
    result.setProcessTime(new Date());
  145.  
    result.setFundChannelCode(req.getFundChannelCode());
  146.  
    result.setApiType(FundChannelApiType.DEBIT);
  147.  
    result.setExtension(jsonObject.toString());
  148.  
    result.setInstOrderNo(req.getInstOrderNo());
  149.  
    logger.info("返回支付平台结果:" JSON.toJSONString(result));
  150.  
    return ResultWrapper.ok().putData(result);
  151.  
    }
  152.  
     
  153.  
    }catch (Exception e) {
  154.  
    logger.error("资金源[" req.getFundChannelCode() "]支付异常", e);
  155.  
    Map<String, String> map = new HashMap<String,String>();
  156.  
    map.put("fundsChannel", req.getFundChannelCode());
  157.  
    result.setExtension(JSON.toJSONString(map));
  158.  
    result = builFalidFundinResponse(req, "支付异常", ReturnCode.FAILED, ReturnCode.FAILED,
  159.  
    StringUtils.EMPTY_STRING);
  160.  
    ResultWrapper.error().putData(result);
  161.  
    }
  162.  
    return null;
  163.  
    }
学新通
  1.  
    /**
  2.  
    * 微信调起支付参数
  3.  
    * 返回参数如有不理解 请访问微信官方文档
  4.  
    * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_1_4.shtml
  5.  
    *
  6.  
    * @param prepayId 微信下单返回的prepay_id
  7.  
    * @param appId 应用ID(appid)
  8.  
    * @param privateKeyFilePath 私钥的地址
  9.  
    * @return 当前调起支付所需的参数
  10.  
    * @throws Exception
  11.  
    */
  12.  
    private JSONObject WxTuneUp(String prepayId, String appId, String privateKeyFilePath) throws Exception {
  13.  
    String time = System.currentTimeMillis() / 1000 "";
  14.  
    String nonceStr = UUID.randomUUID().toString().replace("-", "");
  15.  
    String packageStr = "prepay_id=" prepayId;
  16.  
    ArrayList<String> list = new ArrayList<>();
  17.  
    list.add(appId);
  18.  
    list.add(time);
  19.  
    list.add(nonceStr);
  20.  
    list.add(packageStr);
  21.  
    //加载签名
  22.  
    String packageSign = WeiXinPaySignUtils.sign(WeiXinPaySignUtils.buildSignMessage(list).getBytes(), privateKeyFilePath);
  23.  
    JSONObject jsonObject = new JSONObject();
  24.  
    jsonObject.put("appId", appId);
  25.  
    jsonObject.put("timeStamp", time);
  26.  
    jsonObject.put("nonceStr", nonceStr);
  27.  
    jsonObject.put("packages", packageStr);
  28.  
    jsonObject.put("signType", "RSA");
  29.  
    jsonObject.put("paySign", packageSign);
  30.  
    return jsonObject;
  31.  
    }
学新通

查询:

  1.  
    @PostMapping("/query")
  2.  
    public ResultWrapper<Map<String,Object>> query(@RequestBody String request) {
  3.  
     
  4.  
    logger.info("PayChannelOrder->Channel微信V3支付结果查询请求参数:" request);
  5.  
    ChannelFundResult result = new ChannelFundResult();
  6.  
    QueryRequest req = JSON.parseObject(request, QueryRequest.class);
  7.  
    result.setApiType(req.getApiType());
  8.  
    logger.info("PayChannelOrder->Channel微信V3支付结果查询请求参数转换对象:" req);
  9.  
    Properties properties = propertyHelper.getProperties(req.getFundChannelCode());
  10.  
    try {
  11.  
    String mock_switch = properties.getProperty(WXPAYFundChannelKey.MOCK_SWITCH);
  12.  
    if("true".equals(mock_switch)){//开关开启返回mock数据
  13.  
    result.setFundChannelCode(req.getFundChannelCode());
  14.  
    result.setInstOrderNo(req.getInstOrderNo());
  15.  
    result.setSuccess(true);
  16.  
    result.setApiType(req.getApiType());
  17.  
    result.setRealAmount(req.getAmount());
  18.  
    result.setInstOrderNo(req.getInstOrderNo());
  19.  
    result.setApiResultCode("0000");
  20.  
    result.setApiResultSubCode("SUCCESS");
  21.  
    result.setApiResultMessage("注意:当前为mock数据!:查询成功");
  22.  
    result.setResultMessage("注意:当前为mock数据!:交易成功");
  23.  
    result.setApiResultSubMessage("注意:当前为mock数据!:交易成功");
  24.  
    logger.info("注意这是mock数据!");
  25.  
    return ResultWrapper.ok().putData(result);
  26.  
    }
  27.  
    String mchId = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_MCHID);
  28.  
    String url =properties.getProperty(WXPAYFundChannelKey.QUERY_ORDER_URL);
  29.  
    url = url.replace("{out_trade_no}",req.getInstOrderNo());
  30.  
    url = url.concat("?mchid=").concat(mchId);
  31.  
    logger.info("【微信V3支付】->请求URL:{}",url);
  32.  
    String mchSerialNo = properties.getProperty(WXPAYFundChannelKey.MCH_SERIAL_NO);
  33.  
    String privateKeyFilePath = properties.getProperty(WXPAYFundChannelKey.PRIVATE_KEY_FILE_PATH);
  34.  
    String token = WeiXinPaySignUtils.getToken("GET", HttpUrl.parse(url_prex url),
  35.  
    mchId, mchSerialNo, privateKeyFilePath, "");
  36.  
    //创建httpclient对象
  37.  
    CloseableHttpClient client = HttpClients.createDefault();
  38.  
    HttpGet httpGet = new HttpGet(url_prex url);
  39.  
    //设置header信息
  40.  
    //指定报文头【Content-type】、【User-Agent】
  41.  
    httpGet.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
  42.  
    httpGet.setHeader("Accept", "application/json");
  43.  
    httpGet.setHeader("Authorization",
  44.  
    "WECHATPAY2-SHA256-RSA2048 " token);
  45.  
    CloseableHttpResponse response = client.execute(httpGet);
  46.  
    String bodyString = EntityUtils.toString(response.getEntity());//得到我的这个请求的body请求信息
  47.  
    logger.info("【微信V3支付】->返回结果->Entity:{}",bodyString);
  48.  
    Map<String, String> resultMap = MapUtil.jsonToMap(bodyString);
  49.  
    int statusCode = response.getStatusLine().getStatusCode();
  50.  
    if (statusCode == 200) {
  51.  
    if("SUCCESS".equals(resultMap.get("trade_state"))){
  52.  
    result.setFundChannelCode(req.getFundChannelCode());
  53.  
    result.setInstOrderNo(req.getInstOrderNo());
  54.  
    result.setApiResultCode(resultMap.get("trade_state"));
  55.  
    result.setRealAmount(req.getAmount());
  56.  
    result.setApiResultSubCode(resultMap.get("trade_state"));
  57.  
    result.setResultMessage(resultMap.get("trade_state_desc"));
  58.  
    result.setApiResultMessage(resultMap.get("trade_state_desc"));
  59.  
    result.setApiResultSubMessage(resultMap.get("trade_state_desc"));
  60.  
    result.setSuccess(true);
  61.  
    result.setInstReturnOrderNo(resultMap.get("transaction_id"));
  62.  
    result.setExtension(bodyString);
  63.  
    logger.info("查询响应结果:" JSON.toJSONString(result));
  64.  
    return ResultWrapper.ok().putData(result);
  65.  
    }else{
  66.  
    result.setFundChannelCode(req.getFundChannelCode());
  67.  
    result.setInstOrderNo(req.getInstOrderNo());
  68.  
    result.setApiResultCode(resultMap.get("trade_state"));
  69.  
    result.setRealAmount(req.getAmount());
  70.  
    result.setApiResultSubCode(resultMap.get("trade_state"));
  71.  
    result.setResultMessage(resultMap.get("trade_state_desc"));
  72.  
    result.setApiResultMessage(resultMap.get("trade_state_desc"));
  73.  
    result.setApiResultSubMessage(resultMap.get("trade_state_desc"));
  74.  
    result.setSuccess(false);
  75.  
    result.setInstReturnOrderNo(resultMap.get("transaction_id"));
  76.  
    result.setExtension(bodyString);
  77.  
    logger.info("查询响应结果:" JSON.toJSONString(result));
  78.  
    return ResultWrapper.ok().putData(result);
  79.  
    }
  80.  
    }else if(statusCode == 204){
  81.  
    logger.info("请求状态码为204");
  82.  
    }else {
  83.  
    logger.info("查询订单失败,响应码 ==>{},响应信息是===>{}",statusCode,bodyString);
  84.  
    result.setFundChannelCode(req.getFundChannelCode());
  85.  
    result.setInstOrderNo(req.getInstOrderNo());
  86.  
    result.setApiResultCode(String.valueOf(statusCode));
  87.  
    result.setRealAmount(req.getAmount());
  88.  
    result.setApiResultMessage(bodyString);
  89.  
    result.setResultMessage(bodyString);
  90.  
    result.setSuccess(false);
  91.  
    result.setExtension(bodyString);
  92.  
    logger.info("查询响应结果:" JSON.toJSONString(result));
  93.  
    return ResultWrapper.ok().putData(result);
  94.  
    }
  95.  
    }catch (Exception ex) {
  96.  
    logger.error("查询异常", ex);
  97.  
    result = buildFaildChannelFundResult("签约支付异常", ReturnCode.FAILED, FundChannelApiType.SINGLE_QUERY);
  98.  
    return ResultWrapper.error().putData(result);
  99.  
    }
  100.  
    return null;
  101.  
    }
学新通

支付成功异步通知:

  1.  
    @PostMapping("/notify/{fundChannelCode}")
  2.  
    public Object notify(@PathVariable("fundChannelCode") String fundChannelCode,@RequestBody String data) {
  3.  
    logger.info("通知数据:" data);
  4.  
    logger.info("fundChannelCode:" fundChannelCode);
  5.  
    ChannelRequest channelRequest = new ChannelRequest();
  6.  
    channelRequest.setFundChannelCode(fundChannelCode);
  7.  
    channelRequest.setApiType(FundChannelApiType.DEBIT);
  8.  
    channelRequest.getExtension().put("notifyMsg", data);
  9.  
    Properties properties = propertyHelper.getProperties(channelRequest.getFundChannelCode());
  10.  
    String v3key =properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_MCHSECRETKEY);
  11.  
    ChannelFundResult result = wxPayResultNotifyService.v3notify(channelRequest,v3key);
  12.  
    //调用发送MQ消息,更新订单状态
  13.  
    Map<String,Object> map = new HashMap<String,Object>();
  14.  
    map.put("message", result);
  15.  
    //消息被序列化后发送
  16.  
    AmqoRequrst requrst = new AmqoRequrst();
  17.  
    requrst.setExchange("exchange.payresult.process");
  18.  
    requrst.setRoutingKey("key.payresult.process");
  19.  
    requrst.setMap(map);
  20.  
    logger.info("发送MQ消息:" JSON.toJSONString(requrst));
  21.  
    amqpService.sendMessage(requrst);
  22.  
    logger.info("MQ消息发送完毕");
  23.  
    //通知业务系统
  24.  
    //resultNotifyFacade.notifyBiz(instOrderResult.getInstOrderNo(),xmlToMap);
  25.  
    String return_result = "{ \n"
  26.  
    " \"code\": \"SUCCESS\",\n"
  27.  
    " \"message\": \"成功\"\n"
  28.  
    "}";
  29.  
    return return_result;
  30.  
    }
学新通

退款:

  1.  
    @PostMapping("/refund")
  2.  
    public ResultWrapper<Map<String,Object>> refund(@RequestBody String request) {
  3.  
    logger.info("PayChannelOrder->Channel微信支付V3退款渠道请求参数:" request);
  4.  
    ChannelFundResult result = new ChannelFundResult();
  5.  
    ChannelFundRequest req = JSON.parseObject(request, ChannelFundRequest.class);
  6.  
    logger.info("PayChannelOrder->Channel微信支付V3退款渠道请求参数转换对象:" req);
  7.  
    Properties properties = propertyHelper.getProperties(req.getFundChannelCode());
  8.  
    //判断mock开关是否打开,是否要返回mock数据
  9.  
    String mock_switch = properties.getProperty(WXPAYFundChannelKey.MOCK_SWITCH);
  10.  
    if("true".equals(mock_switch)){//开关开启返回mock数据
  11.  
    result.setApiType(req.getApiType());
  12.  
    result.setRealAmount(req.getAmount());
  13.  
    result.setInstOrderNo(req.getInstOrderNo());
  14.  
    result.setProcessTime(new Date());
  15.  
    result = MockResultData.mockResule(result);
  16.  
    logger.info("注意这是mock数据!");
  17.  
    return ResultWrapper.ok().putData(result);
  18.  
    }
  19.  
    try {
  20.  
    RefundVO refundVO = new RefundVO();
  21.  
    // transaction_id
  22.  
    String transactionId = req.getExtension().get("transactionId");
  23.  
    if(StringUtils.isNotBlank(transactionId)){
  24.  
    refundVO.setTransaction_id(transactionId);
  25.  
    }
  26.  
    String outTradeNo = req.getExtension().get("originalOutTradeNo");
  27.  
    if(StringUtils.isNotBlank(outTradeNo)){
  28.  
    refundVO.setOut_trade_no(outTradeNo);
  29.  
    }
  30.  
    refundVO.setOut_refund_no(req.getInstOrderNo());
  31.  
    String refundReason = req.getExtension().get("refundReason");
  32.  
    if(StringUtils.isNotBlank(refundReason)){
  33.  
    refundVO.setReason(refundReason);
  34.  
    }
  35.  
    String refundNotifyUrl = req.getExtension().get("refundNotifyUrl");
  36.  
    if(StringUtils.isNotBlank(refundNotifyUrl)){
  37.  
    refundVO.setNotify_url(refundNotifyUrl);
  38.  
    }
  39.  
    refundVO.setFunds_account("AVAILABLE");
  40.  
    RefounAmount amount = new RefounAmount();
  41.  
    String originalAmount = req.getExtension().get("originalAmount");
  42.  
    String refounAmount = req.getExtension().get("refounAmount");
  43.  
    int total = Integer.parseInt(AmountUtils.Yuan2Fen(originalAmount));
  44.  
    int refund = Integer.parseInt(AmountUtils.Yuan2Fen(refounAmount));
  45.  
    amount.setTotal(total);
  46.  
    amount.setCurrency("CNY");
  47.  
    amount.setRefund(refund);
  48.  
    refundVO.setAmount(amount);
  49.  
    String jsonStr = JSON.toJSONString(refundVO);
  50.  
    logger.info("【微信V3支付】->退款请求参数JSON:{}",jsonStr);
  51.  
    // 发送请求
  52.  
    String url =properties.getProperty(WXPAYFundChannelKey.REFUNDS_QUERY_URL);
  53.  
    logger.info("【微信V3支付配置】->【退款请求URL】:{}",url);
  54.  
    //创建httpclient对象
  55.  
    CloseableHttpClient client = HttpClients.createDefault();
  56.  
    //创建post方式请求对象
  57.  
    HttpPost httpPost = new HttpPost(url_prex url);
  58.  
    //装填参数
  59.  
    StringEntity s = new StringEntity(jsonStr, charset);
  60.  
    s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
  61.  
    "application/json"));
  62.  
    //设置参数到请求对象中
  63.  
    httpPost.setEntity(s);
  64.  
    String mchSerialNo = properties.getProperty(WXPAYFundChannelKey.MCH_SERIAL_NO);
  65.  
    String privateKeyFilePath = properties.getProperty(WXPAYFundChannelKey.PRIVATE_KEY_FILE_PATH);
  66.  
    String mchId = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_MCHID);
  67.  
    logger.info("【微信V3支付配置】->【微信商户ID】:" mchId);
  68.  
    String token = WeiXinPaySignUtils.getToken("POST", HttpUrl.parse(url_prex url), mchId, mchSerialNo, privateKeyFilePath, jsonStr);
  69.  
    //设置header信息
  70.  
    //指定报文头【Content-type】、【User-Agent】
  71.  
    httpPost.setHeader("Content-type", "application/json");
  72.  
    httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
  73.  
    httpPost.setHeader("Accept", "application/json");
  74.  
    httpPost.setHeader("Authorization",
  75.  
    "WECHATPAY2-SHA256-RSA2048 " token);
  76.  
    //执行请求操作,并拿到结果(同步阻塞)
  77.  
    CloseableHttpResponse response = client.execute(httpPost);
  78.  
    //获取结果实体
  79.  
    HttpEntity entity = response.getEntity();
  80.  
    String body = "";
  81.  
    if (entity != null) {
  82.  
    //按指定编码转换结果实体为String类型
  83.  
    body = EntityUtils.toString(entity, charset);
  84.  
    }
  85.  
    EntityUtils.consume(entity);
  86.  
    //释放链接
  87.  
    response.close();
  88.  
    JSONObject jsonObject = JSONObject.fromObject(body);
  89.  
    logger.info("【微信V3支付】->返回结果->:{}",jsonObject);
  90.  
    StatusLine statusLine = response.getStatusLine();
  91.  
    logger.info("【微信支付】发起退款, request={}", JsonUtil.toJson(refundVO));
  92.  
    int statusCode = response.getStatusLine().getStatusCode();
  93.  
    if(statusCode == 200){
  94.  
    String refundId = (String)jsonObject.get("refund_id");
  95.  
    if(StringUtils.isBlank(refundId)){
  96.  
    result.setApiResultCode(String.valueOf(statusLine.getStatusCode()));
  97.  
    result.setApiResultMessage(statusLine.getReasonPhrase());
  98.  
    result.setResultMessage(statusLine.getReasonPhrase());
  99.  
    result.setSuccess(false);
  100.  
    result.setRealAmount(req.getAmount());
  101.  
    result.setProcessTime(new Date());
  102.  
    result.setFundChannelCode(req.getFundChannelCode());
  103.  
    result.setApiType(FundChannelApiType.DEBIT);
  104.  
    result.setExtension(body);
  105.  
    result.setInstOrderNo(req.getInstOrderNo());
  106.  
    logger.info("返回支付平台结果:" JSON.toJSONString(result));
  107.  
    return ResultWrapper.ok().putData(result);
  108.  
    }else{
  109.  
    result.setApiResultCode((String)jsonObject.get("status"));
  110.  
    result.setApiResultMessage((String)jsonObject.get("user_received_account"));
  111.  
    result.setResultMessage((String)jsonObject.get("user_received_account"));
  112.  
    result.setSuccess(true);
  113.  
    result.setRealAmount(new BigDecimal(refounAmount));
  114.  
    result.setProcessTime(new Date());
  115.  
    result.setFundChannelCode(req.getFundChannelCode());
  116.  
    result.setApiType(FundChannelApiType.DEBIT);
  117.  
    result.setExtension(body);
  118.  
    result.setInstOrderNo(req.getInstOrderNo());
  119.  
    logger.info("返回支付平台结果:" JSON.toJSONString(result));
  120.  
    return ResultWrapper.ok().putData(result);
  121.  
    }
  122.  
    }else{
  123.  
    logger.info("查询订单失败,响应码 ==>{},响应信息是===>{}",statusCode,body);
  124.  
    result.setFundChannelCode(req.getFundChannelCode());
  125.  
    result.setInstOrderNo(req.getInstOrderNo());
  126.  
    result.setApiResultCode(String.valueOf(statusCode));
  127.  
    result.setRealAmount(req.getAmount());
  128.  
    result.setApiResultMessage(body);
  129.  
    result.setResultMessage(body);
  130.  
    result.setSuccess(false);
  131.  
    result.setExtension(body);
  132.  
    logger.info("查询响应结果:" JSON.toJSONString(result));
  133.  
    return ResultWrapper.ok().putData(result);
  134.  
    }
  135.  
     
  136.  
    }catch (Exception e) {
  137.  
    logger.error("资金源[" req.getFundChannelCode() "]支付异常", e);
  138.  
    Map<String, String> map = new HashMap<String,String>();
  139.  
    map.put("fundsChannel", req.getFundChannelCode());
  140.  
    result.setExtension(JSON.toJSONString(map));
  141.  
    result = builFalidFundinResponse(req, "支付异常", ReturnCode.FAILED, ReturnCode.FAILED,
  142.  
    StringUtils.EMPTY_STRING);
  143.  
    ResultWrapper.error().putData(result);
  144.  
    }
  145.  
    return null;
  146.  
    }
学新通

退款查询:

  1.  
    @PostMapping("/refundQuery")
  2.  
    public ResultWrapper<Map<String,Object>> refundQuery(@RequestBody String request) {
  3.  
     
  4.  
    logger.info("PayChannelOrder->Channel微信支付退款结果查询请求参数:" request);
  5.  
    ChannelFundResult result = new ChannelFundResult();
  6.  
    QueryRequest req = JSON.parseObject(request, QueryRequest.class);
  7.  
    result.setApiType(req.getApiType());
  8.  
    logger.info("PayChannelOrder->Channel微信支付退款结果查询请求参数转换对象:" req);
  9.  
    Properties properties = propertyHelper.getProperties(req.getFundChannelCode());
  10.  
    try {
  11.  
    String mock_switch = properties.getProperty(WXPAYFundChannelKey.MOCK_SWITCH);
  12.  
    if("true".equals(mock_switch)){//开关开启返回mock数据
  13.  
    result.setFundChannelCode(req.getFundChannelCode());
  14.  
    result.setInstOrderNo(req.getInstOrderNo());
  15.  
    result.setSuccess(true);
  16.  
    result.setApiType(req.getApiType());
  17.  
    result.setRealAmount(req.getAmount());
  18.  
    result.setInstOrderNo(req.getInstOrderNo());
  19.  
    result.setApiResultCode("0000");
  20.  
    result.setApiResultSubCode("SUCCESS");
  21.  
    result.setApiResultMessage("注意:当前为mock数据!:查询成功");
  22.  
    result.setResultMessage("注意:当前为mock数据!:交易成功");
  23.  
    result.setApiResultSubMessage("注意:当前为mock数据!:交易成功");
  24.  
    logger.info("注意这是mock数据!");
  25.  
    return ResultWrapper.ok().putData(result);
  26.  
    }
  27.  
    String mchId = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_MCHID);
  28.  
    String url =properties.getProperty(WXPAYFundChannelKey.REFUNDS_QUERY_URL);
  29.  
    url = url.replace("{out_refund_no}",req.getOriginalInstOrderNo());
  30.  
    logger.info("【微信V3支付】->退款查询请求URL:{}",url);
  31.  
    String mchSerialNo = properties.getProperty(WXPAYFundChannelKey.MCH_SERIAL_NO);
  32.  
    String privateKeyFilePath = properties.getProperty(WXPAYFundChannelKey.PRIVATE_KEY_FILE_PATH);
  33.  
    String token = WeiXinPaySignUtils.getToken("GET", HttpUrl.parse(url_prex url),
  34.  
    mchId, mchSerialNo, privateKeyFilePath, "");
  35.  
    //创建httpclient对象
  36.  
    CloseableHttpClient client = HttpClients.createDefault();
  37.  
    HttpGet httpGet = new HttpGet(url_prex url);
  38.  
    //设置header信息
  39.  
    //指定报文头【Content-type】、【User-Agent】
  40.  
    httpGet.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
  41.  
    httpGet.setHeader("Accept", "application/json");
  42.  
    httpGet.setHeader("Authorization",
  43.  
    "WECHATPAY2-SHA256-RSA2048 " token);
  44.  
    CloseableHttpResponse response = client.execute(httpGet);
  45.  
    String bodyString = EntityUtils.toString(response.getEntity());//得到我的这个请求的body请求信息
  46.  
    logger.info("【微信V3支付】->返回结果->Entity:{}",bodyString);
  47.  
    Map<String, String> resultMap = MapUtil.jsonToMap(bodyString);
  48.  
    int statusCode = response.getStatusLine().getStatusCode();
  49.  
    String refund_id = resultMap.get("refund_id");
  50.  
    if (statusCode == 200 && StringUtils.isNotBlank(refund_id)) {
  51.  
    result.setFundChannelCode(req.getFundChannelCode());
  52.  
    result.setInstOrderNo(req.getInstOrderNo());
  53.  
    result.setApiResultCode(resultMap.get("status"));
  54.  
    Map<String,String> amountMap = MapUtil.jsonToMap(resultMap.get("amount"));
  55.  
    result.setRealAmount(new BigDecimal(AmountUtils.Fen2Yuan(Long.parseLong(amountMap.get("refund")))));
  56.  
    result.setResultMessage(resultMap.get("user_received_account"));
  57.  
    result.setApiResultMessage(resultMap.get("user_received_account"));
  58.  
    result.setSuccess(true);
  59.  
    result.setInstReturnOrderNo(refund_id);
  60.  
    result.setExtension(bodyString);
  61.  
    logger.info("退款查询响应结果:" JSON.toJSONString(result));
  62.  
    return ResultWrapper.ok().putData(result);
  63.  
     
  64.  
    }else {
  65.  
    logger.info("查询订单失败,响应码 ==>{},响应信息是===>{}",statusCode,bodyString);
  66.  
    result.setFundChannelCode(req.getFundChannelCode());
  67.  
    result.setInstOrderNo(req.getInstOrderNo());
  68.  
    result.setApiResultCode(String.valueOf(statusCode));
  69.  
    result.setRealAmount(req.getAmount());
  70.  
    result.setApiResultMessage(bodyString);
  71.  
    result.setResultMessage(bodyString);
  72.  
    result.setSuccess(false);
  73.  
    result.setExtension(bodyString);
  74.  
    logger.info("查询响应结果:" JSON.toJSONString(result));
  75.  
    return ResultWrapper.ok().putData(result);
  76.  
    }
  77.  
    }catch (Exception ex) {
  78.  
    logger.error("查询异常", ex);
  79.  
    result = buildFaildChannelFundResult("签约支付异常", ReturnCode.FAILED, FundChannelApiType.SINGLE_QUERY);
  80.  
    return ResultWrapper.error().putData(result);
  81.  
    }
  82.  
    }
学新通

下载对账文件

  1.  
    @PostMapping("/downloadBill")
  2.  
    public ResultWrapper<Map<String,Object>> downloadBill(@RequestBody String request) {
  3.  
    logger.info("PayChannelOrder->Channel微信V3支付账单请求参数:" request);
  4.  
    ChannelFundResult result = new ChannelFundResult();
  5.  
    ChannelFundRequest req = JSON.parseObject(request, ChannelFundRequest.class);
  6.  
    logger.info("PayChannelOrder->Channel微信V3支付账单渠道请求参数转换对象:" req);
  7.  
    Properties properties = propertyHelper.getProperties(req.getFundChannelCode());
  8.  
    //判断mock开关是否打开,是否要返回mock数据
  9.  
    String mock_switch = properties.getProperty(WXPAYFundChannelKey.MOCK_SWITCH);
  10.  
    if("true".equals(mock_switch)){//开关开启返回mock数据
  11.  
    result.setApiType(req.getApiType());
  12.  
    result.setRealAmount(req.getAmount());
  13.  
    result.setInstOrderNo(req.getInstOrderNo());
  14.  
    result.setProcessTime(new Date());
  15.  
    result = MockResultData.mockResule(result);
  16.  
    logger.info("注意这是mock数据!");
  17.  
    return ResultWrapper.ok().putData(result);
  18.  
    }
  19.  
    try {
  20.  
    Map<String, String> extension = req.getExtension();
  21.  
    String bill_dowload_url = properties.getProperty(WXPAYFundChannelKey.KEY_TRADE_BILL_URL);
  22.  
    logger.info("【微信对账下载】->【对账单下载】:" bill_dowload_url);
  23.  
    String billType = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_BILL_TYPE);
  24.  
    // 对账类型: ALL,返回当日所有订单信息,默认值 SUCCESS,返回当日成功支付的订单 REFUND,返回当日退款订单
  25.  
    logger.info("【微信对账下载】->【微信对账类型】:" billType);
  26.  
    String billDirPath = properties.getProperty(WXPAYFundChannelKey.KEY_BILL_DIR_PATH);
  27.  
    logger.info("【微信对账下载】->【对账文件路径】:" billDirPath);
  28.  
    Map<String,String> map = new HashMap<String,String>();
  29.  
    String mchSerialNo = properties.getProperty(WXPAYFundChannelKey.MCH_SERIAL_NO);
  30.  
    logger.info("【微信对账下载】->【微信证书编号】:" mchSerialNo);
  31.  
    String privateKeyFilePath = properties.getProperty(WXPAYFundChannelKey.PRIVATE_KEY_FILE_PATH);
  32.  
    logger.info("【微信对账下载】->【微信秘钥路径】:" privateKeyFilePath);
  33.  
    String mchId = properties.getProperty(WXPAYFundChannelKey.KEY_WEIXIN_MCHID);
  34.  
    logger.info("【微信对账下载】->【微信商户号】:" mchId);
  35.  
    map.put("bill_dowload_url", url_prex bill_dowload_url);
  36.  
    map.put("bill_date", extension.get("billDate"));
  37.  
    map.put("billDirPath", billDirPath);
  38.  
    map.put("bill_type", billType);
  39.  
    map.put("tar_type", "GZIP");
  40.  
    map.put("mchSerialNo", mchSerialNo);
  41.  
    map.put("privateKeyFilePath", privateKeyFilePath);
  42.  
    map.put("mchId", mchId);
  43.  
    File file = winXinFileDown.v3fileDown(map);
  44.  
    result.setSuccess(true);
  45.  
    String bill_file = file.getCanonicalPath();
  46.  
    Map<String, String> extensionMap = new HashMap<String, String>();
  47.  
    extensionMap.put("bill_file", bill_file);
  48.  
    result.setInstOrderNo(req.getInstOrderNo());
  49.  
    result.setExtension(JSON.toJSONString(extensionMap));
  50.  
    result.setFundChannelCode(req.getFundChannelCode());
  51.  
    result.setApiResultCode("0000");
  52.  
    result.setRealAmount(req.getAmount());
  53.  
    result.setResultMessage("对账文件下载成功");
  54.  
    result.setApiResultMessage("对账文件下载成功");
  55.  
    result.setSuccess(true);
  56.  
    return ResultWrapper.ok().putData(result);
  57.  
    }catch (Exception e) {
  58.  
    logger.error("资金源[" req.getFundChannelCode() "]账单下载异常", e);
  59.  
    Map<String, String> map = new HashMap<String,String>();
  60.  
    map.put("fundsChannel", req.getFundChannelCode());
  61.  
    result.setExtension(JSON.toJSONString(map));
  62.  
    result = builFalidFundinResponse(req, "账单下载异常", ReturnCode.FAILED, ReturnCode.FAILED,
  63.  
    StringUtils.EMPTY_STRING);
  64.  
    ResultWrapper.error().putData(result);
  65.  
    }
  66.  
    return null;
  67.  
    }
学新通

有疑问欢迎联系我,GitHub - panda726548/yiranpay: 聚合支付是一种第四方支付服务。简而言之,第三方支付提供的是资金清算通道,而聚合支付提供的是支付基础之上的多种衍生服务。聚合支付服务”不具备支付牌照,而是通过聚合多种第三方支付平台、合作银行及其他服务商接口等支付工具的综合支付服务。聚合支付不进行资金清算,但能够根据商户的需求进行个性化定制,形成支付通道资源优势互补,具有中立性、灵活性、便捷性等特点。目前已经对接微信,支付宝,银联支付等渠道。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcehie
系列文章
更多 icon
同类精品
更多 icon
继续加载