微信境外支付与跨城冗灾
IJPay 2.3.0 版本开始支持微信境外支付
境外支付与国内支付区别
仅仅只是域名不一样,接口以及签名方式完全一样。所以就有以下的封装。
微信支付域名
- apihk.mch.weixin.qq.com(建议接入点:东南亚)
- apius.mch.weixin.qq.com(建议接入点:其它)
- api.mch.weixin.qq.com(建议接入点:中国国内)
- api2.mch.weixin.qq.com(建议接入点:中国国内备用)
IJPay 中是通过枚举 WxDomain 来实现, 所有支付方式接口是通过枚举 WxApiType 来实现,如有遗漏欢迎反馈 PR
实现原理
实现原理非常简单粗暴:字符串拼接(微信支付域名+沙箱环境(仿真测试系统)+接口URL)
例如:统一下单
- 东南亚: https://apihk.mch.weixin.qq.com/pay/unifiedorder
- 其它: https://apius.mch.weixin.qq.com/pay/unifiedorder
- 中国国内: https://api.mch.weixin.qq.com/pay/unifiedorder
- 中国国内备用: https://api2.mch.weixin.qq.com/pay/unifiedorder
- 中国国内仿真系统: https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder
获取接口URL并发起请求
获取接口URL有三个重载方法:
WxPayApi.getReqUrl(wxApiType)
国内正式环境WxPayApi.getReqUrl(wxApiType,isSandBox)
国内正式环境与沙箱环境WxPayApi.getReqUrl(wxApiType,wxDomain,isSandBox)
自定义
通过接口发起请求有四个方法:
WxPayApi.executionByGet(apiUrl, params)
发起 Get 请求WxPayApi.execution(apiUrl, params)
发起 POST 请求WxPayApi.execution(apiUrl, params, certPath, certPass)
双向证书发起 POST 请求WxPayApi.execution(apiUrl, params, certFileInputStream, certPass)
双向证书发起 POST 请求
IJPay 默认 Http 客户端是使用 HuTool 中的 Http 客户端工具类 HttpUtil 来实现。 如需扩展请参考 扩展 HTTP 请求 ,自定定义 HTTP 请求也很容易实现 跨城冗灾
/**
* 获取接口请求的 URL
*
* @param wxApiType {@link WxApiType} 支付 API 接口枚举
* @return {@link String} 返回完整的接口请求URL
*/
public static String getReqUrl(WxApiType wxApiType) {
return getReqUrl(wxApiType, null, false);
}
/**
* 获取接口请求的 URL
*
* @param wxApiType {@link WxApiType} 支付 API 接口枚举
* @param isSandBox 是否是沙箱环境
* @return {@link String} 返回完整的接口请求URL
*/
public static String getReqUrl(WxApiType wxApiType, boolean isSandBox) {
return getReqUrl(wxApiType, null, isSandBox);
}
/**
* 获取接口请求的 URL
*
* @param wxApiType {@link WxApiType} 支付 API 接口枚举
* @param wxDomain {@link WxDomain} 支付 API 接口域名枚举
* @param isSandBox 是否是沙箱环境
* @return {@link String} 返回完整的接口请求URL
*/
public static String getReqUrl(WxApiType wxApiType, WxDomain wxDomain, boolean isSandBox) {
if (wxDomain == null) {
wxDomain = WxDomain.CHINA;
}
return wxDomain.getType()
.concat(isSandBox ? WxApiType.SAND_BOX_NEW.getType() : "")
.concat(wxApiType.getType());
}
/**
* 发起请求
*
* @param apiUrl 接口 URL
* 通过 {@link WxPayApi#getReqUrl(WxApiType)}
* 或者 {@link WxPayApi#getReqUrl(WxApiType, WxDomain, boolean)} 来获取
* @param params 接口请求参数
* @return {@link String} 请求返回的结果
*/
public static String execution(String apiUrl, Map<String, String> params) {
return doPost(apiUrl, params);
}
/**
* 发起请求
*
* @param apiUrl 接口 URL
* 通过 {@link WxPayApi#getReqUrl(WxApiType)}
* 或者 {@link WxPayApi#getReqUrl(WxApiType, WxDomain, boolean)} 来获取
* @param params 接口请求参数
* @return {@link String} 请求返回的结果
*/
public static String executionByGet(String apiUrl, Map<String, Object> params) {
return doGet(apiUrl, params);
}
/**
* 发起请求
*
* @param apiUrl 接口 URL
* 通过 {@link WxPayApi#getReqUrl(WxApiType)}
* 或者 {@link WxPayApi#getReqUrl(WxApiType, WxDomain, boolean)} 来获取
* @param params 接口请求参数
* @param certPath 证书文件目录
* @param certPass 证书密码
* @return {@link String} 请求返回的结果
*/
public static String execution(String apiUrl, Map<String, String> params, String certPath, String certPass) {
return doPostSSL(apiUrl, params, certPath, certPass);
}
/**
* 发起请求
*
* @param apiUrl 接口 URL
* 通过 {@link WxPayApi#getReqUrl(WxApiType)}
* 或者 {@link WxPayApi#getReqUrl(WxApiType, WxDomain, boolean)} 来获取
* @param params 接口请求参数
* @param certFile 证书文件输入流
* @param certPass 证书密码
* @return {@link String} 请求返回的结果
*/
public static String execution(String apiUrl, Map<String, String> params, InputStream certFile, String certPass) {
return doPostSSL(apiUrl, params, certFile, certPass);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
如何使用?
统一下单为例:
/**
* 统一下单
*
* @param params 请求参数
* @return {@link String} 请求返回的结果
*/
public static String pushOrder(Map<String, String> params) {
return pushOrder(false, null, params);
}
/**
* 统一下单
*
* @param isSandbox 是否是沙盒环境
* @param params 请求参数
* @return {@link String} 请求返回的结果
*/
public static String pushOrder(boolean isSandbox, Map<String, String> params) {
return pushOrder(isSandbox, null, params);
}
/**
* 统一下单
*
* @param isSandbox 是否是沙盒环境
* @param wxDomain {@link WxDomain} 支付 API 接口域名枚举
* @param params 请求参数
* @return {@link String} 请求返回的结果
*/
public static String pushOrder(boolean isSandbox, WxDomain wxDomain, Map<String, String> params) {
return execution(getReqUrl(WxApiType.UNIFIED_ORDER, wxDomain, isSandbox), params);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32