接口规则
<p>[TOC]</p>
<h1>文档目的</h1>
<p>鸿雁平台对接外部渠道,如果渠道方需要使用专用接口,即对接使用渠道方的接口文档。如果渠道方没有定制接口需求,则按照该接口文档规范进行交互</p>
<h1>文档说明</h1>
<p>文档中必传字段展示,Y标识必传,CY标识条件必传,N标识不必传</p>
<h1>接口信息</h1>
<p>1. 统一使用post请求,json格式,加密传输,秘钥另外提供</p>
<p>2. 签名算法可能并不止包括,“RSA”,“MD5”,“AES”</p>
<table>
<thead>
<tr>
<th>传输方式</th>
<th>为保证交易安全性,采用HTTPS传输</th>
</tr>
</thead>
<tbody>
<tr>
<td>提交方式</td>
<td>采用POST方法提交</td>
</tr>
<tr>
<td>数据格式</td>
<td>提交和返回数据都为text/plain格式</td>
</tr>
<tr>
<td>参数</td>
<td>String(加密后的密文)</td>
</tr>
<tr>
<td>字符编码</td>
<td>统一采用UTF-8字符编码</td>
</tr>
<tr>
<td>签名算法</td>
<td>MD5、AES算法</td>
</tr>
</tbody>
</table>
<h1>参数规定</h1>
<table>
<thead>
<tr>
<th style="text-align: left;">字符</th>
<th style="text-align: left;">一般数据类型,一般使用String接收</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">金额</td>
<td style="text-align: left;">BigDecimal类型</td>
</tr>
<tr>
<td style="text-align: left;">数值</td>
<td style="text-align: left;">Integer类型</td>
</tr>
<tr>
<td style="text-align: left;">日期/日期时间</td>
<td style="text-align: left;">date/dateTime类型</td>
</tr>
<tr>
<td style="text-align: left;">字符</td>
<td style="text-align: left;">一般数据类型,一般使用String接收</td>
</tr>
<tr>
<td style="text-align: left;">是否为必录</td>
<td style="text-align: left;">Y-必录;CY-条件必录;N或空白:非必录</td>
</tr>
</tbody>
</table>
<h1>headers中的信息</h1>
<table>
<thead>
<tr>
<th style="text-align: left;">字段名称</th>
<th style="text-align: left;">字段代码</th>
<th style="text-align: left;">字段类型</th>
<th style="text-align: left;">是否必传</th>
<th style="text-align: left;">字段描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">渠道编码</td>
<td style="text-align: left;">policySource</td>
<td style="text-align: left;">varchar</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">保司提供</td>
</tr>
<tr>
<td style="text-align: left;">签名</td>
<td style="text-align: left;">sign</td>
<td style="text-align: left;">varchar</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;"><a href="#签名说明">签名说明</a></td>
</tr>
<tr>
<td style="text-align: left;">订单号</td>
<td style="text-align: left;">orderNo</td>
<td style="text-align: left;">varchar</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;"></td>
</tr>
<tr>
<td style="text-align: left;">token</td>
<td style="text-align: left;">token</td>
<td style="text-align: left;">varchar</td>
<td style="text-align: left;">CY</td>
<td style="text-align: left;"></td>
<td></td>
</tr>
</tbody>
</table>
<h1>环境地址</h1>
<ul>
<li>测试环境: <a href="https://hermesgyb.zhlic.net">https://hermesgyb.zhlic.net</a></li>
<li>生产环境: <a href="https://gyb.zhlic.net">https://gyb.zhlic.net</a></li>
</ul>
<h1>interfaceType</h1>
<ul>
<li><strong>head中的interfaceType(<b style='color:red'>可使用接口最后一个方法名</b>)</strong></li>
</ul>
<table>
<thead>
<tr>
<th style="text-align: left;">接口</th>
<th style="text-align: left;">是否必传</th>
<th style="text-align: left;">描述</th>
<th style="text-align: left;">interfaceType</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">核保</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">核保逻辑</td>
<td style="text-align: left;">proposalOrder</td>
</tr>
<tr>
<td style="text-align: left;">承保</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">承保逻辑</td>
<td style="text-align: left;">policyOrder</td>
</tr>
<tr>
<td style="text-align: left;">获取缴费链接</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">获取承保缴费链接</td>
<td style="text-align: left;">payUrl</td>
</tr>
<tr>
<td style="text-align: left;">出单通知接口</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">出单通知接口</td>
<td style="text-align: left;">paySucc</td>
</tr>
<tr>
<td style="text-align: left;">退保试算</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">退保试算逻辑</td>
<td style="text-align: left;">refundCal</td>
</tr>
<tr>
<td style="text-align: left;">退保</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">退保逻辑</td>
<td style="text-align: left;">refundOrder</td>
</tr>
<tr>
<td style="text-align: left;">退保通知接口</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">退保通知接口</td>
<td style="text-align: left;">refundNotice</td>
</tr>
<tr>
<td style="text-align: left;">续费接口</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">获取缴费链接</td>
<td style="text-align: left;">renew</td>
</tr>
<tr>
<td style="text-align: left;">续费成功通知接口</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">渠道续费通知</td>
<td style="text-align: left;">renewNotice</td>
</tr>
<tr>
<td style="text-align: left;">token生成接口</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">token生成</td>
<td style="text-align: left;">getToken</td>
</tr>
<tr>
<td style="text-align: left;">影像信息上传接口</td>
<td style="text-align: left;">Y</td>
<td style="text-align: left;">影像信息上传</td>
<td style="text-align: left;">uploadImage</td>
</tr>
</tbody>
</table>
<h1>报文说明</h1>
<p>1. 整体报文使用AES对称加密传输,请求过来的需要是密文报文,秘钥另外提供</p>
<ol>
<li>渠道返回报文也需要进行AES加密,保司需要对返回报文进行AES解密。</li>
</ol>
<h1>签名说明</h1>
<p>1. 整体报文使用AES对称加密传输,请求过来的需要是密文报文,秘钥另外提供</p>
<p>2. <a href="#headers中的信息">headers</a>中增加数据校验,及将加密后的整体报文,再将其使用MD5加密获取sign值,即sign=MD5(加密报文+key) 小写32位</p>
<p>3. 测试环境aesKey、md5Key。生产环境上线前提供</p>
<pre><code> key = &quot;fuahdfujhauidhiuawse&quot;;
aesKey = &quot;sadedfjekashciew&quot;;</code></pre>
<h2>如下图</h2>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=219b980b543c7c5c62718c2d2b0cca24&amp;file=file.jpg" alt="请求说明" /></p>
<h1>签名、加解密demo</h1>
<p>[报文信息.zip](<a href="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=794bd3b9274821f312bcce52184ccee4">https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=794bd3b9274821f312bcce52184ccee4</a> "[报文信息.zip")</p>
<h1>签名</h1>
<pre><code class="language-java">package com.huanong.avatar.common.utils;
import org.springframework.util.Base64Utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
private static final String KEY_MD5 = &quot;MD5&quot;;
public static String md5(String str, String encoding) {
byte[] hash = null;
try {
hash = MessageDigest.getInstance(KEY_MD5).digest(str.getBytes(encoding));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b &amp; 0xFF) &lt; 0x10) {
hex.append(&quot;0&quot;);
}
hex.append(Integer.toHexString(b &amp; 0xFF));
}
return hex.toString();
}
}
</code></pre>
<h1>报文加密、解密</h1>
<pre><code class="language-java">
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.huanong.avatar.common.utils.MD5Utils;
import org.apache.commons.net.util.Base64;
import org.springframework.util.Base64Utils;
import sun.security.provider.Sun;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
public class EncodeTest {
private final static String key = &quot;fuahdfujhauidhiuawse&quot;;
private final static String aesKey = &quot;sadedfjekashciew&quot;;
private static final String SECURITY_PROVIDER = &quot;SUN&quot;;
private final static String DData = &quot;{\&quot;avatarInsureBody\&quot;:{\&quot;holderInfo\&quot;:{\&quot;address\&quot;:\&quot;全国\&quot;,\&quot;birthday\&quot;:\&quot;1982-07-23\&quot;,\&quot;email\&quot;:\&quot;363854962@qq.com\&quot;,\&quot;gender\&quot;:\&quot;2\&quot;,\&quot;idCode\&quot;:\&quot;220724198207231823\&quot;,\&quot;idType\&quot;:\&quot;0\&quot;,\&quot;mobile\&quot;:\&quot;15506588298\&quot;,\&quot;name\&quot;:\&quot;王微\&quot;,\&quot;type\&quot;:\&quot;0\&quot;},\&quot;insureOrderInfo\&quot;:{\&quot;effectTime\&quot;:\&quot;2021-04-29 00:00:00\&quot;,\&quot;firstPeriodPremium\&quot;:960,\&quot;invalidTime\&quot;:\&quot;2022-04-28 23:59:59\&quot;,\&quot;isRenewPolicy\&quot;:false,\&quot;issueTime\&quot;:\&quot;2021-04-27 09:11:48\&quot;,\&quot;nextPeriodPremium\&quot;:0,\&quot;payFrequency\&quot;:\&quot;0\&quot;,\&quot;payMode\&quot;:\&quot;1\&quot;,\&quot;planCode\&quot;:\&quot;260812\&quot;,\&quot;presenterPolicy\&quot;:false,\&quot;productCode\&quot;:\&quot;2608\&quot;,\&quot;totalAmount\&quot;:6000000,\&quot;totalPremium\&quot;:960.00},\&quot;insuredInfos\&quot;:[{\&quot;address\&quot;:\&quot;全国\&quot;,\&quot;birthday\&quot;:\&quot;1990-03-07\&quot;,\&quot;gender\&quot;:\&quot;1\&quot;,\&quot;hasSocial\&quot;:false,\&quot;idCode\&quot;:\&quot;110101199003078153\&quot;,\&quot;idType\&quot;:\&quot;0\&quot;,\&quot;mobile\&quot;:\&quot;13792889545\&quot;,\&quot;name\&quot;:\&quot;王思思\&quot;,\&quot;relType\&quot;:2,\&quot;type\&quot;:\&quot;0\&quot;}]},\&quot;head\&quot;:{\&quot;interfaceType\&quot;:\&quot;/general/proposalOrder\&quot;,\&quot;orderNo\&quot;:\&quot;BC0000001\&quot;,\&quot;policySource\&quot;:\&quot;HN_BC\&quot;,\&quot;reqTime\&quot;:\&quot;2021-04-27 09:11:48\&quot;,\&quot;uuid\&quot;:\&quot;ca32571e-3b57-4041-b85a-34b5db0b333f\&quot;}}&quot;;
private final static String EData = &quot;35URoRsQtIQSC5HS8YWj7NckJeLAe423pWGNkGufMYArowNr1Y/QMYBp11tfb0ClJM5VAmH7Up1zWaotOB6RfCWKDpsfiQ6/BL55T4fmjSDxdGYvzCvEx4pR8ORpKAjR8ALp5caXI1b0P/cYk8uK1rtXarLvgzSNxWOyKNnaLEC4H4DXYsyUH7SvByt+hJyvDu18NDf4GKsy0tMNvxEpy2A404s+JqZCma1M1i+AyRYnBKVCpzm9Hr1zM1yl05NPqmQxzFuepCXhbVEkYhKqOH2dLzwgaABHFrLg7oUJa5ahu/Z5CpYsJ8GJg/UY6IPfeGDgoNMLgmdXOq58mKoSmcjo04nFofLade+8mmBLYWK44mikQ1BC/Df0uRpDuB8RpqLjlCiUV7PXTg+DlVlZuGE7Sj5XLTOYl6DJ4Fg5SiJbatOLRZuVhI394vJ2xdVCIIzUwFA+fwPAstcXS1zR9EKRiwwOzkYS1t0Xe6ZCTHhdFuPFdxNrvgfbQyeKlSjZAtmgnkCf+S5XO5NQrSelFSE4RdyBY7wc4r61oep+ZcyxoHCVqALmkjMH+Bu7N/bgfLPifGxoZX6/NYFT5o94STe/bg8+yvCCgibJM9ZknxPvTB0vg9rEEq5MXgK+ui8VE+/otjncBrrjvkejM9S2OLaTCIJY1E7lCJL2PyB3+b1phQZ7i9UQUVRMM/bV5ttC0SIPh22vQFMxAZSIJirXpEn0TJyGl/GsRDNWjDqtSTiqmp7uSF1CNhZIdQjyCh+iuqNTcYJcWRZjWa38dNYe3ybiH7Hl6A6W44m+LZxZyndRQcXdGXqo87BP5heQMOokttAuCoIm2irTaXldEGHM1IseD/AIRpLjhRLEqut5yvEZ2Zjz2hDSUnhJcwNqqmXmOcU9PqY6fOxUsH4UqJ/hYfdon8cJDxdHsHkRvwwCJWNxtDnOF7YdbSNvMsjA+J00i9Vj13p2JGGXtAzMqYXAj2F7fapZ/uoe32Qza6uxKxlIfNWlgq4fHc3AFkKlk614Cx/TLDNwmQBIpG8dccgpmHdwsjbBDok3bkwxhnxeGDrJc8HzVS5HRB7f2+doYeBULun5WEqv1UobTaixpszL8M1rqTNDspluYj29AC9fV1BLSAf1rFpm5otxHYy7CDSZfPqJ/w2ih+ooijXLExMxtFCqxn22ZtJIL+MDnfOkU3NJHU1MYrY9Ho2Sjxnl0xTJcvMzM2JtYCNRJut9ZwFzng==&quot;;
public static String encode(String data) {
int mode = 1;
try {
byte[] content = data.getBytes(StandardCharsets.UTF_8);
SecretKey secretKey = getSecretKey(aesKey);
// 创建密钥
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), &quot;AES&quot;);
// 创建密码器
Cipher cipher = Cipher.getInstance(&quot;AES&quot;);
// 初始化
cipher.init(mode, keySpec);
byte[] result = cipher.doFinal(content);
return new String(Base64.encodeBase64(result));
} catch (Exception e) {
System.err.println(&quot;AES密文处理异常&quot; + e);
e.printStackTrace();
}
return null;
}
public static String decode(String data) {
long startTime = System.currentTimeMillis();
try {
byte[] decode = Base64Utils.decode(data.getBytes());
// 解密
byte[] decryptResult = decrypt(decode, aesKey);
String decryptContent = new String(decryptResult, &quot;UTF-8&quot;);
return decryptContent;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e + &quot;解密失败&quot;);
}
}
public static String getSign(String data) {
String newSign = MD5Utils.md5(data + key, &quot;utf-8&quot;);
return newSign;
}
public static SecretKey getSecretKey(String key) {
try {
KeyGenerator gen = KeyGenerator.getInstance(&quot;AES&quot;);
if (null == Security.getProvider(SECURITY_PROVIDER)) {
Security.addProvider(new Sun());
}
SecureRandom secureRandom = SecureRandom.getInstance(&quot;SHA1PRNG&quot;);
secureRandom.setSeed(key.getBytes());
gen.init(128, secureRandom);
return gen.generateKey();
} catch (Exception e) {
throw new RuntimeException(&quot;初始化秘钥出现异常&quot;);
}
}
public static byte[] decrypt(byte[] content, String password) {
try {
SecureRandom random = SecureRandom.getInstance(&quot;SHA1PRNG&quot;);
random.setSeed(password.getBytes());
KeyGenerator kgen = KeyGenerator.getInstance(&quot;AES&quot;);
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, &quot;AES&quot;);
// 创建密码器
Cipher cipher = Cipher.getInstance(&quot;AES&quot;);
// 初始化
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
// 加密
return result;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String encode = encode(DData);
System.out.println(&quot;加密:&quot; + encode);
String sign = getSign(encode);
System.out.println(&quot;签名:&quot; + sign);
String decode = decode(EData);
System.out.println(&quot;解密:&quot; + decode);
HttpRequest request = HttpUtil.createPost(&quot;https://porsche-avatar.chinahuanong.com.cn/avatar/general/proposalOrder&quot;);
request.header(&quot;sign&quot;, sign);
request.header(&quot;orderNo&quot;, &quot;123&quot;);
request.header(&quot;policySource&quot;, &quot;123&quot;);
request.header(&quot;content-type&quot;,&quot;text/plain&quot;);
// request.contentType(&quot;text/plain&quot;);
request.body(encode);
HttpResponse execute = request.execute();
String respBody = execute.body();
String deBody = decode(respBody);
System.out.println(&quot;解密:&quot; + deBody);
}
}
</code></pre>
<h1>PHP加解密示例</h1>
<pre><code class="language-php">&lt;?php
/**
* 加密
*/
function encrypt(string $data): string
{
$key = &#039;sadedfjekashciew&#039;;
$aesKey = substr(openssl_digest(openssl_digest($key, &#039;sha1&#039;, true), &#039;sha1&#039;, true), 0, 16);
return base64_encode(openssl_encrypt($data, &#039;AES-128-ECB&#039;, $aesKey, OPENSSL_RAW_DATA));
}
/**
* 解密
*/
function decrypt(string $data): string
{
$key = &#039;sadedfjekashciew&#039;;
$aesKey = substr(openssl_digest(openssl_digest($key, &#039;sha1&#039;, true), &#039;sha1&#039;, true), 0, 16);
return openssl_decrypt(base64_decode($data), &#039;AES-128-ECB&#039;, $aesKey, OPENSSL_RAW_DATA);
}
$json = &#039;{&quot;avatarInsureBody&quot;:{&quot;insureOrderInfo&quot;:{&quot;productCode&quot;:&quot;PDC00177&quot;,&quot;planCode&quot;:&quot;PLC00881&quot;,&quot;issueTime&quot;:&quot;2023-11-10 14:57:01&quot;,&quot;effectTime&quot;:&quot;2023-11-10 14:57:01&quot;,&quot;invalidTime&quot;:&quot;2023-11-10 17:57:01&quot;,&quot;periodDay&quot;:&quot;30&quot;,&quot;payFrequency&quot;:&quot;1&quot;,&quot;isRenewPolicy&quot;:false,&quot;parentPolicyNo&quot;:&quot;&quot;,&quot;firstPeriodPremium&quot;:&quot;3&quot;,&quot;totalPremium&quot;:&quot;3&quot;,&quot;totalAmount&quot;:&quot;110000&quot;,&quot;presenterPolicy&quot;:true,&quot;payMode&quot;:2},&quot;holderInfo&quot;:{&quot;name&quot;:&quot;太原合旭网络科技有限公司&quot;,&quot;idType&quot;:&quot;6&quot;,&quot;idCode&quot;:&quot;91149900MA7XHL8Q3M&quot;,&quot;province&quot;:&quot;140000&quot;,&quot;city&quot;:&quot;140100&quot;,&quot;district&quot;:&quot;140105&quot;,&quot;unitResidence&quot;:&quot;太原市小店区长风街道和信商座3202&quot;,&quot;linkerName&quot;:&quot;吉晓彬&quot;,&quot;linkerPhone&quot;:&quot;13100008431&quot;,&quot;industryType1&quot;:&quot;U99&quot;,&quot;unitType&quot;:&quot;0007&quot;,&quot;extensionInfo&quot;:{&quot;linkerIdentifyNo&quot;:&quot;142430199109301637&quot;,&quot;linkerIdentifyType&quot;:&quot;0&quot;,&quot;companyAddress&quot;:&quot;山西转型综合改革示范区学府产业园平阳路426号大和昌业29层2901室&quot;}},&quot;insuredInfos&quot;:[{&quot;name&quot;:&quot;鹿坤&quot;,&quot;idType&quot;:&quot;0&quot;,&quot;idCode&quot;:&quot;140411199510194419&quot;,&quot;gender&quot;:&quot;1&quot;,&quot;birthday&quot;:&quot;1995-10-19&quot;,&quot;mobile&quot;:&quot;15035514195&quot;,&quot;type&quot;:&quot;0&quot;,&quot;relType&quot;:&quot;0&quot;,&quot;extensionInfo&quot;:{&quot;schoolName&quot;:&quot;山东华宇工学院&quot;}}]},&quot;head&quot;:{&quot;policySource&quot;:&quot;PHN_ZTJJ_CKYW&quot;,&quot;reqTime&quot;:&quot;2023-11-10 14:57:01&quot;,&quot;interfaceType&quot;:&quot;proposalOrder&quot;,&quot;orderNo&quot;:&quot;20231031153158644564&quot;,&quot;uuid&quot;:&quot;xmx202311101699599421&quot;}}&#039;;
$encryptData = encrypt($json);
echo &quot;密文:&quot; . $encryptData . PHP_EOL;
$md5Key = &#039;fuahdfujhauidhiuawse&#039;;
$sign = md5($encryptData . $md5Key);
echo &quot;sign:&quot; . $sign . PHP_EOL;
$decryptData = decrypt($encryptData);
echo &quot;明文:&quot; . $decryptData;
?&gt;
</code></pre>
<h1>.NET 加密示例</h1>
<pre><code>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace InsuranceSys.UI.Common
{
public class AESEncrypter
{
/// &lt;summary&gt;
/// 生成对应JAVA AES加密方法的KEY值
/// &lt;/summary&gt;
/// &lt;param name=&quot;aesKey&quot;&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
private static byte[] encryptJavaAes(string aesKey)
{
byte[] keyArray = null;
using (var sha1 = new SHA1CryptoServiceProvider())
{
byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(aesKey));
var rd = sha1.ComputeHash(hash);
keyArray = rd.Take(16).ToArray();
/* 将字节流转换成字符串输出
Base64Encoder coder = new Base64Encoder();
coder.GetEncoded(keyArray);
* */
}
return keyArray;
}
/// &lt;summary&gt;
/// .NET对JAVA进行AES加密
/// &lt;/summary&gt;
/// &lt;param name=&quot;encryptString&quot;&gt;需要加密的字符串&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static string AESEncryptForJava(string encryptString, string aesKey)
{
if (string.IsNullOrEmpty(encryptString)) return null;
Byte[] toEncryptArray = Encoding.UTF8.GetBytes(encryptString);
RijndaelManaged rm = new RijndaelManaged
{
Key = encryptJavaAes(aesKey),//Convert.FromBase64String(encryptKey),
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateEncryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
/// &lt;summary&gt;
/// 解密加密的字符串
/// &lt;/summary&gt;
/// &lt;param name=&quot;toDecrypt&quot;&gt;需要解密的字符串&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static string AESDecryptForJava(string toDecrypt,string aesKey)
{
string aeskey = System.Configuration.ConfigurationManager.AppSettings[&quot;aeskey&quot;];
byte[] keyArray = encryptJavaAes(aesKey);//Convert.FromBase64String(key);
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB; //必须设置为ECB
rDel.Padding = PaddingMode.PKCS7; //必须设置为PKCS7
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
}
}
</code></pre>
<h1>关于电子保单保函403的问题</h1>
<p>保司使用的电子保函、电子保单链接<strong>有可能</strong>为HTTP请求302的重定向链接,会出现无法直接下载获取的情况,jdk8以上请使用该方法再试一次方可解决403或无法下载电子保单保函的问题</p>
<h3>JAVA</h3>
<pre><code class="language-java">import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 从网络Url中下载文件并加密成base64
*
* @param urlStr
* @throws IOException
* @return
*/
public static byte[] downLoadByUrlBase64(String urlStr) throws IOException {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置超时间为3秒
conn.setConnectTimeout(5 * 1000);
//302重定向则获取重定向后的地址重新下载
int responseCode = conn.getResponseCode();
if (responseCode == 302) {
return downLoadByUrlBase64(conn.getHeaderField(&quot;location&quot;));
}
//得到输入流
InputStream inputStream = conn.getInputStream();
//获取自己数组
byte[] getData = readInputStream(inputStream);
if (inputStream != null) {
inputStream.close();
}
return getData;
}</code></pre>
<p>上述代码使用了java.net.*可解决403问题,若使用了HttpClient的话请在上述的基础上再加上</p>
<pre><code class="language-java">setRedirectsEnabled(false) //默认为 true 请设置成false</code></pre>
<h3>PHP</h3>
<pre><code class="language-php">function downloadByUrlBase64($urlStr) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $urlStr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
$data = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 302) {
return downloadByUrlBase64($data);
} else {
return base64_encode($data);
}
}</code></pre>
<h3>python</h3>
<pre><code class="language-python">import requests
import base64
def download_by_url_base64(url):
response = requests.get(url, timeout=5)
if response.status_code == 302:
return download_by_url_base64(response.headers[&#039;location&#039;])
elif response.status_code != 200:
raise Exception(&#039;请求失败,HTTP状态码为{}&#039;.format(response.status_code))
else:
return base64.b64encode(response.content).decode()</code></pre>