Skip to content

Commit cff5616

Browse files
authored
🆕 #3404 【小程序】增加同城配送相关接口,同时为WxMaService增加了API签名支持
1 parent f6e300b commit cff5616

35 files changed

+3626
-574
lines changed
165 KB
Loading
297 KB
Loading
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# 使用API签名
2+
3+
如果对API签名不了解,可先阅读微信文档 [服务端API签名指南](https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html)
4+
5+
有API数据加密与签名两种功能,此处按照微信文档,简称为签名。
6+
7+
## 程序内设置
8+
9+
[WxMaConfig](src/main/java/cn/binarywang/wx/miniapp/config/WxMaConfig.java)类增加了几个属性,分别对应小程序内设置的签名密钥等。
10+
11+
* apiSignatureAesKey
12+
* apiSignatureAesKeySn
13+
* apiSignatureRsaPrivateKey
14+
* apiSignatureRsaPrivateKeySn
15+
16+
这4个属性需要按照小程序后台设置。
17+
18+
## 小程序后台设置/查看签名用密钥
19+
20+
在小程序后台,开发管理 -> 开发设置 -> API安全处,可以看到如下图界面。
21+
22+
![图一](../images/api-signature/api-signature-1.png)
23+
24+
上图中A处对应 apiSignatureAesKeySn; B处对应apiSignatureAesKey; C处对应apiSignatureRsaPrivateKeySn
25+
26+
apiSignatureRsaPrivateKey 在上图中****对应,C处右侧是公钥,apiSignatureRsaPrivateKey 需要的是私钥。
27+
28+
可点击图上右上角的修改,打开如下图的设置页面
29+
30+
![图二](../images/api-signature/api-signature-2.png)
31+
32+
首先确保对称密钥选中 AES256,非对称密钥选中RSA。不要选SM4和SM2。
33+
(如果需要支持SM4/SM2,可修改BaseWxMaServiceImpl.java中postWithSignature方法中相应部分实现)。
34+
35+
在API非对称密钥中下方左侧有个「随机生成密钥对」,点击它,然后点它右侧的「下载私钥」,之后点击「确认」保存。
36+
下载得到的文件是PKCS1格式的私钥,用openssl可转成PKCS8格式。apiSignatureRsaPrivateKey 需要设置的是PKCS8格式的私钥。
37+
38+
注意:
39+
40+
1. 如果不先点击「随机生成密钥对」,直接点击「下载私钥」得到的是公钥,公钥在这里没有用途。
41+
2. 打开下载的文件,第一行是「-----BEGIN RSA PRIVATE KEY-----」说明是PKCS1格式私钥。
42+
3. PKCS8格式第一行是「-----BEGIN PRIVATE KEY-----」
43+
4. 转换命令 `openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in PKCS1格式密钥文件名 -out 新的PKCS8格式密钥文件名`
44+
5. 如果密钥文件有 PUBLIC KEY 字样,说明下载了公钥,重新生成密钥对,下载私钥
45+
46+
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package cn.binarywang.wx.miniapp.api;
2+
3+
import cn.binarywang.wx.miniapp.bean.intractiy.*;
4+
import java.util.List;
5+
import me.chanjar.weixin.common.error.WxErrorException;
6+
7+
/**
8+
* 微信小程序 物流服务 同城配送服务API <br>
9+
* *不是*即时配送接口,两个相近,容易混淆<br>
10+
* 微信相关接口 <br>
11+
* https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/business/intracity_service.html
12+
*/
13+
public interface WxMaIntracityService {
14+
15+
/** 申请开通门店权限 */
16+
void apply() throws WxErrorException;
17+
18+
/** 创建门店 */
19+
String createStore(WxMaStore store) throws WxErrorException;
20+
21+
/**
22+
* 更新门店;只更新store中不为null的部分 wxStoreId和outStoreId至少要有一个不为null,根据这2个来更新。 仅支持更新 storeName orderPattern
23+
* serviceTransPrefer addressInfo几个属性
24+
*/
25+
void updateStore(WxMaStore store) throws WxErrorException;
26+
27+
/** 查询门店(列出所有门店) */
28+
List<WxMaStore> listAllStores() throws WxErrorException;
29+
30+
/** 根据wx_store_id查询门店 */
31+
WxMaStore queryStoreByWxStoreId(String wxStoreId) throws WxErrorException;
32+
33+
/** 根据 out_store_id 查询门店 */
34+
List<WxMaStore> queryStoreByOutStoreId(String outStoreId) throws WxErrorException;
35+
36+
/** 门店运费充值,返回充值URL */
37+
String storeCharge(WxMaStoreChargeRequest request) throws WxErrorException;
38+
39+
/** 门店运费退款,返回退款金额 */
40+
int storeRefund(WxMaStoreRefundRequest request) throws WxErrorException;
41+
42+
/** 门店运费流水查询 */
43+
WxMaStoreFlowResponse<? extends WxMaStoreFlowResponse.BasicFlowRecord> queryFlow(
44+
WxMaQueryFlowRequest request) throws WxErrorException;
45+
46+
/** 查询门店余额 */
47+
WxMaStoreBalance balanceQuery(String wxStoreId, String serviceTransId, PayMode payMode)
48+
throws WxErrorException;
49+
50+
/**
51+
* 设置扣费主体 <br>
52+
* 接口调用成功后,小程序的管理员会收到模板消息,点击模板消息确认更改门店扣费主体后,修改生效。
53+
*/
54+
void setPayMode(PayMode payMode) throws WxErrorException;
55+
56+
/** 查询扣费主体 */
57+
WxMaGetPayModeResponse getPayMode() throws WxErrorException;
58+
59+
/** 查询运费 */
60+
WxMaAddOrderResponse preAddOrder(WxMaPreAddOrderRequest request) throws WxErrorException;
61+
62+
/** 创建配送单 */
63+
WxMaAddOrderResponse addOrder(WxMaAddOrderRequest order) throws WxErrorException;
64+
65+
/** 查询配送单 根据wxOrderId */
66+
WxMaOrder queryOrderByWxOrderId(String wxOrderId) throws WxErrorException;
67+
68+
/** 依据商户订单号 查询配送单 */
69+
WxMaOrder queryOrderByStoreOrderId(String wxStoreId, String storeOrderId) throws WxErrorException;
70+
71+
/** 依据微信订单号 查询配送单 */
72+
WxMaCancelOrderResponse cancelOrderByWxOrderId(
73+
String wxOrderId, int cancelReasonId, String cancelReason) throws WxErrorException;
74+
75+
/** 依据商户订单号 查询配送单 */
76+
WxMaCancelOrderResponse cancelOrderByStoreOrderId(
77+
String wxStoreId, String storeOrderId, int cancelReasonId, String cancelReason)
78+
throws WxErrorException;
79+
80+
/**
81+
* 查询支持同城配送的城市
82+
*
83+
* @param serviceTransId 运力ID,传NULL则返回所有
84+
*/
85+
List<WxMaTransCity> getCity(String serviceTransId) throws WxErrorException;
86+
}

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaService.java

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package cn.binarywang.wx.miniapp.api;
22

3+
import cn.binarywang.wx.miniapp.bean.WxMaApiResponse;
34
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
45
import cn.binarywang.wx.miniapp.config.WxMaConfig;
6+
import cn.binarywang.wx.miniapp.executor.ApiSignaturePostRequestExecutor;
7+
import com.google.gson.JsonObject;
8+
import java.util.Map;
59
import java.util.function.Function;
610
import me.chanjar.weixin.common.error.WxErrorException;
711
import me.chanjar.weixin.common.service.WxImgProcService;
@@ -11,33 +15,25 @@
1115
import me.chanjar.weixin.common.util.http.RequestExecutor;
1216
import me.chanjar.weixin.common.util.http.RequestHttp;
1317

14-
import java.util.Map;
15-
1618
/**
1719
* The interface Wx ma service.
1820
*
1921
* @author <a href="https://github.com/binarywang">Binary Wang</a>
2022
*/
2123
public interface WxMaService extends WxService {
22-
/**
23-
* 获取access_token.
24-
*/
25-
String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
26-
String GET_STABLE_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/stable_token";
24+
/** 获取access_token. */
25+
String GET_ACCESS_TOKEN_URL =
26+
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
2727

28+
String GET_STABLE_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/stable_token";
2829

29-
/**
30-
* The constant JSCODE_TO_SESSION_URL.
31-
*/
30+
/** The constant JSCODE_TO_SESSION_URL. */
3231
String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
33-
/**
34-
* getPaidUnionId
35-
*/
32+
33+
/** getPaidUnionId */
3634
String GET_PAID_UNION_ID_URL = "https://api.weixin.qq.com/wxa/getpaidunionid";
3735

38-
/**
39-
* 导入抽样数据
40-
*/
36+
/** 导入抽样数据 */
4137
String SET_DYNAMIC_DATA_URL = "https://api.weixin.qq.com/wxa/setdynamicdata";
4238

4339
/**
@@ -51,28 +47,31 @@ public interface WxMaService extends WxService {
5147

5248
/**
5349
* 导入抽样数据
50+
*
5451
* <pre>
5552
* 第三方通过调用微信API,将数据写入到setdynamicdata这个API。每个Post数据包不超过5K,若数据过多可开多进(线)程并发导入数据(例如:数据量为十万量级可以开50个线程并行导数据)。
5653
* 文档地址:https://wsad.weixin.qq.com/wsad/zh_CN/htmledition/widget-docs-v3/html/custom/quickstart/implement/import/index.html
5754
* http请求方式:POST http(s)://api.weixin.qq.com/wxa/setdynamicdata?access_token=ACCESS_TOKEN
5855
* </pre>
5956
*
6057
* @param lifespan 数据有效时间,秒为单位,一般为86400,一天一次导入的频率
61-
* @param type 用于标识数据所属的服务类目
62-
* @param scene 1代表用于搜索的数据
63-
* @param data 推送到微信后台的数据列表,该数据被微信用于流量分配,注意该字段为string类型而不是object
58+
* @param type 用于标识数据所属的服务类目
59+
* @param scene 1代表用于搜索的数据
60+
* @param data 推送到微信后台的数据列表,该数据被微信用于流量分配,注意该字段为string类型而不是object
6461
* @throws WxErrorException .
6562
*/
6663
void setDynamicData(int lifespan, String type, int scene, String data) throws WxErrorException;
6764

6865
/**
66+
*
67+
*
6968
* <pre>
7069
* 验证消息的确来自微信服务器.
7170
* 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN
7271
* </pre>
7372
*
7473
* @param timestamp the timestamp
75-
* @param nonce the nonce
74+
* @param nonce the nonce
7675
* @param signature the signature
7776
* @return the boolean
7877
*/
@@ -88,6 +87,8 @@ public interface WxMaService extends WxService {
8887
String getAccessToken() throws WxErrorException;
8988

9089
/**
90+
*
91+
*
9192
* <pre>
9293
* 获取access_token,本方法线程安全.
9394
* 且在多线程同时刷新时只刷新一次,避免超出2000次/日的调用次数上限
@@ -106,6 +107,8 @@ public interface WxMaService extends WxService {
106107
String getAccessToken(boolean forceRefresh) throws WxErrorException;
107108

108109
/**
110+
*
111+
*
109112
* <pre>
110113
* 用户支付完成后,获取该用户的 UnionId,无需用户授权。本接口支持第三方平台代理查询。
111114
*
@@ -114,33 +117,45 @@ public interface WxMaService extends WxService {
114117
* 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api/getPaidUnionId.html
115118
* </pre>
116119
*
117-
* @param openid 必填 支付用户唯一标识
120+
* @param openid 必填 支付用户唯一标识
118121
* @param transactionId 非必填 微信支付订单号
119-
* @param mchId 非必填 微信支付分配的商户号,和商户订单号配合使用
120-
* @param outTradeNo 非必填 微信支付商户订单号,和商户号配合使用
122+
* @param mchId 非必填 微信支付分配的商户号,和商户订单号配合使用
123+
* @param outTradeNo 非必填 微信支付商户订单号,和商户号配合使用
121124
* @return UnionId. paid union id
122125
* @throws WxErrorException .
123126
*/
124-
String getPaidUnionId(String openid, String transactionId, String mchId, String outTradeNo) throws WxErrorException;
127+
String getPaidUnionId(String openid, String transactionId, String mchId, String outTradeNo)
128+
throws WxErrorException;
125129

126130
/**
131+
*
132+
*
127133
* <pre>
128134
* Service没有实现某个API的时候,可以用这个,
129135
* 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。
130136
* 可以参考,{@link MediaUploadRequestExecutor}的实现方法
131137
* </pre>
132138
*
133-
* @param <T> .
134-
* @param <E> .
139+
* @param <T> .
140+
* @param <E> .
135141
* @param executor 执行器
136-
* @param uri 接口请求地址
137-
* @param data 参数或请求数据
142+
* @param uri 接口请求地址
143+
* @param data 参数或请求数据
138144
* @return . t
139145
* @throws WxErrorException the wx error exception
140146
*/
141147
<T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException;
142148

149+
WxMaApiResponse execute(
150+
ApiSignaturePostRequestExecutor executor,
151+
String uri,
152+
Map<String, String> headers,
153+
String data)
154+
throws WxErrorException;
155+
143156
/**
157+
*
158+
*
144159
* <pre>
145160
* 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试.
146161
* 默认:1000ms
@@ -151,6 +166,8 @@ public interface WxMaService extends WxService {
151166
void setRetrySleepMillis(int retrySleepMillis);
152167

153168
/**
169+
*
170+
*
154171
* <pre>
155172
* 设置当微信系统响应系统繁忙时,最大重试次数.
156173
* 默认:5次
@@ -177,7 +194,7 @@ public interface WxMaService extends WxService {
177194
/**
178195
* Map里 加入新的 {@link WxMaConfig},适用于动态添加新的微信公众号配置.
179196
*
180-
* @param miniappId 小程序标识
197+
* @param miniappId 小程序标识
181198
* @param configStorage 新的微信配置
182199
*/
183200
void addConfig(String miniappId, WxMaConfig configStorage);
@@ -190,8 +207,8 @@ public interface WxMaService extends WxService {
190207
void removeConfig(String miniappId);
191208

192209
/**
193-
* 注入多个 {@link WxMaConfig} 的实现. 并为每个 {@link WxMaConfig} 赋予不同的 {@link String mpId} 值
194-
* 随机采用一个{@link String mpId}进行Http初始化操作
210+
* 注入多个 {@link WxMaConfig} 的实现. 并为每个 {@link WxMaConfig} 赋予不同的 {@link String mpId} 值 随机采用一个{@link
211+
* String mpId}进行Http初始化操作
195212
*
196213
* @param configs WxMaConfig map
197214
*/
@@ -200,7 +217,7 @@ public interface WxMaService extends WxService {
200217
/**
201218
* 注入多个 {@link WxMaConfig} 的实现. 并为每个 {@link WxMaConfig} 赋予不同的 {@link String label} 值
202219
*
203-
* @param configs WxMaConfig map
220+
* @param configs WxMaConfig map
204221
* @param defaultMiniappId 设置一个{@link WxMaConfig} 所对应的{@link String defaultMiniappId}进行Http初始化
205222
*/
206223
void setMultiConfigs(Map<String, WxMaConfig> configs, String defaultMiniappId);
@@ -328,9 +345,7 @@ public interface WxMaService extends WxService {
328345
*/
329346
WxMaPluginService getPluginService();
330347

331-
/**
332-
* 初始化http请求对象.
333-
*/
348+
/** 初始化http请求对象. */
334349
void initHttp();
335350

336351
/**
@@ -403,15 +418,13 @@ public interface WxMaService extends WxService {
403418
*/
404419
WxMaShopAfterSaleService getShopAfterSaleService();
405420

406-
407421
/**
408422
* 返回小程序交易组件-物流服务接口
409423
*
410424
* @return
411425
*/
412426
WxMaShopDeliveryService getShopDeliveryService();
413427

414-
415428
/**
416429
* 返回小程序交易组件-订单服务接口
417430
*
@@ -544,18 +557,21 @@ public interface WxMaService extends WxService {
544557
* @return getWxMaOpenApiService
545558
*/
546559
WxMaOpenApiService getWxMaOpenApiService();
560+
547561
/**
548562
* 小程序短剧管理
549563
*
550564
* @return getWxMaVodService
551565
*/
552566
WxMaVodService getWxMaVodService();
567+
553568
/**
554569
* 小程序虚拟支付
555570
*
556571
* @return getWxMaXPayService
557572
*/
558573
WxMaXPayService getWxMaXPayService();
574+
559575
WxMaExpressDeliveryReturnService getWxMaExpressDeliveryReturnService();
560576

561577
/**
@@ -564,4 +580,14 @@ public interface WxMaService extends WxService {
564580
* @return WxMaPromotionService
565581
*/
566582
WxMaPromotionService getWxMaPromotionService();
583+
584+
String postWithSignature(String url, Object obj) throws WxErrorException;
585+
586+
String postWithSignature(String url, JsonObject jsonObject) throws WxErrorException;
587+
588+
/**
589+
* 微信物流服务 -- 同城配送
590+
* https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/business/intracity_service.html
591+
*/
592+
WxMaIntracityService getIntracityService();
567593
}

0 commit comments

Comments
 (0)