mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2026-03-10 00:13:40 +08:00
🆕 #2646 【微信支付】增加报关v3接口
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package com.github.binarywang.wxpay.service;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.customs.*;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付 支付报关 API.
|
||||
* Created by xifengzhu on 2022/05/05.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/xifengzhu">xifengzhu</a>
|
||||
*/
|
||||
public interface CustomDeclarationService {
|
||||
|
||||
static String DECLARATION_BASE_URL = "https://apihk.mch.weixin.qq.com/global/v3/customs";
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 报关API
|
||||
* 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_1.shtml
|
||||
* </pre>
|
||||
*
|
||||
* @param request
|
||||
* @return 返回数据 declaration result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
DeclarationResult declare(DeclarationRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 报关查询API
|
||||
* 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_3.shtml
|
||||
* </pre>
|
||||
*
|
||||
* @param request
|
||||
* @return 返回数据 declaration query result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
DeclarationQueryResult query(DeclarationQueryRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 身份信息校验API
|
||||
* 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_2.shtml
|
||||
* </pre>
|
||||
*
|
||||
* @param request
|
||||
* @return 返回数据 verify certification result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
VerifyCertificateResult verifyCertificate(VerifyCertificateRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 报关信息修改API
|
||||
* 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_5.shtml
|
||||
* </pre>
|
||||
*
|
||||
* @param request
|
||||
* @return 返回数据 declaration result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
DeclarationResult modify(DeclarationRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 报关重推API
|
||||
* 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_4.shtml
|
||||
* </pre>
|
||||
*
|
||||
* @param request
|
||||
* @return 返回数据 redeclaration result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
RedeclareResult redeclare(RedeclareRequest request) throws WxPayException;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.customs.*;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.CustomDeclarationService;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.chanjar.weixin.common.error.WxRuntimeException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 支付报关 实现.
|
||||
* Created by xifengzhu on 2022/05/05.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/xifengzhu">xifengzhu</a>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CustomDeclarationServiceImpl implements CustomDeclarationService {
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
private final WxPayService payService;
|
||||
|
||||
@Override
|
||||
public DeclarationResult declare(DeclarationRequest request) throws WxPayException {
|
||||
String response = this.payService.postV3(DECLARATION_BASE_URL.concat("/orders"), GSON.toJson(request));
|
||||
return GSON.fromJson(response, DeclarationResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeclarationQueryResult query(DeclarationQueryRequest request) throws WxPayException {
|
||||
String url = String.format("%s/orders?appid=%s&mchid=%s&order_type=%s&order_no=%s&customs=%s&offset=%s&limit=%s",
|
||||
DECLARATION_BASE_URL,
|
||||
request.getAppid(),
|
||||
request.getMchid(),
|
||||
request.getOrderType(),
|
||||
request.getOrderNo(),
|
||||
request.getCustoms(),
|
||||
request.getOffset(),
|
||||
request.getLimit()
|
||||
);
|
||||
String result = this.payService.getV3(url);
|
||||
return GSON.fromJson(result, DeclarationQueryResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCertificateResult verifyCertificate(VerifyCertificateRequest request) throws WxPayException {
|
||||
this.encryptFields(request);
|
||||
String response = this.payService.postV3WithWechatpaySerial(DECLARATION_BASE_URL.concat("/verify-certificate"), GSON.toJson(request));
|
||||
return GSON.fromJson(response, VerifyCertificateResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeclarationResult modify(DeclarationRequest request) throws WxPayException {
|
||||
String response = this.payService.patchV3(DECLARATION_BASE_URL.concat("/orders"), GSON.toJson(request));
|
||||
return GSON.fromJson(response, DeclarationResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedeclareResult redeclare(RedeclareRequest request) throws WxPayException {
|
||||
String response = this.payService.postV3(DECLARATION_BASE_URL.concat("/redeclare"), GSON.toJson(request));
|
||||
return GSON.fromJson(response, RedeclareResult.class);
|
||||
}
|
||||
|
||||
private void encryptFields(VerifyCertificateRequest request) throws WxPayException {
|
||||
try {
|
||||
request.setCertificateId(encryptOAEP(request.getCertificateId()));
|
||||
request.setCertificateName(encryptOAEP(request.getCertificateName()));
|
||||
} catch (Exception e) {
|
||||
throw new WxPayException("敏感信息加密失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private X509Certificate getValidCertificate() {
|
||||
return this.payService.getConfig().getVerifier().getValidCertificate();
|
||||
}
|
||||
|
||||
private String encryptOAEP(String message)
|
||||
throws IllegalBlockSizeException {
|
||||
X509Certificate certificate = getValidCertificate();
|
||||
try {
|
||||
// 身份信息校验 RSA 加密,填充方案使用 `RSAES-PKCS1-v1_5`
|
||||
// https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_2.shtml
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
|
||||
|
||||
byte[] data = message.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] ciphertext = cipher.doFinal(data);
|
||||
return Base64.getEncoder().encodeToString(ciphertext);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
throw new WxRuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IllegalArgumentException("无效的证书", e);
|
||||
} catch (IllegalBlockSizeException | BadPaddingException e) {
|
||||
throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user