@@ -58,7 +58,7 @@ public class WxPayUnifiedOrderV3Result implements Serializable {
5858 /**
5959 * <pre>
6060 * 字段名:二维码链接(NATIVE支付 会返回)
61- * 变量名:h5_url
61+ * 变量名:code_url
6262 * 是否必填:是
6363 * 类型:string[1,512]
6464 * 描述:
@@ -81,6 +81,19 @@ public static class JsapiResult implements Serializable {
8181 private String packageValue ;
8282 private String signType ;
8383 private String paySign ;
84+ /**
85+ * <pre>
86+ * 字段名:预支付交易会话标识
87+ * 变量名:prepay_id
88+ * 是否必填:否(用户可选存储)
89+ * 类型:string[1,64]
90+ * 描述:
91+ * 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时
92+ * 此字段用于支持用户存储prepay_id,以便复用和重新生成支付签名
93+ * 示例值:wx201410272009395522657a690389285100
94+ * </pre>
95+ */
96+ private String prepayId ;
8497
8598 private String getSignStr () {
8699 return String .format ("%s\n %s\n %s\n %s\n " , appId , timeStamp , nonceStr , packageValue );
@@ -106,30 +119,123 @@ private String getSignStr() {
106119 }
107120
108121 public <T > T getPayInfo (TradeTypeEnum tradeType , String appId , String mchId , PrivateKey privateKey ) {
109- String timestamp = String .valueOf (System .currentTimeMillis () / 1000 );
110- String nonceStr = SignUtils .genRandomStr ();
111122 switch (tradeType ) {
112123 case JSAPI :
113- JsapiResult jsapiResult = new JsapiResult ();
114- jsapiResult .setAppId (appId ).setTimeStamp (timestamp )
115- .setPackageValue ("prepay_id=" + this .prepayId ).setNonceStr (nonceStr )
116- //签名类型,默认为RSA,仅支持RSA。
117- .setSignType ("RSA" ).setPaySign (SignUtils .sign (jsapiResult .getSignStr (), privateKey ));
118- return (T ) jsapiResult ;
124+ return (T ) buildJsapiResult (this .prepayId , appId , privateKey );
119125 case H5 :
120126 return (T ) this .h5Url ;
121127 case APP :
122- AppResult appResult = new AppResult ();
123- appResult .setAppid (appId ).setPrepayId (this .prepayId ).setPartnerId (mchId )
124- .setNoncestr (nonceStr ).setTimestamp (timestamp )
125- //暂填写固定值Sign=WXPay
126- .setPackageValue ("Sign=WXPay" )
127- .setSign (SignUtils .sign (appResult .getSignStr (), privateKey ));
128- return (T ) appResult ;
128+ return (T ) buildAppResult (this .prepayId , appId , mchId , privateKey );
129129 case NATIVE :
130130 return (T ) this .codeUrl ;
131131 default :
132132 throw new WxRuntimeException ("不支持的支付类型" );
133133 }
134134 }
135+
136+ /**
137+ * <pre>
138+ * 根据已有的prepay_id生成JSAPI支付所需的参数对象(解耦版本)
139+ * 应用场景:
140+ * 1. 用户已经通过createPartnerOrderV3或unifiedPartnerOrderV3获取了prepay_id
141+ * 2. 用户希望存储prepay_id用于后续复用
142+ * 3. 支付失败后,使用存储的prepay_id重新生成支付签名信息
143+ *
144+ * 使用示例:
145+ * // 步骤1:创建订单并获取prepay_id
146+ * WxPayUnifiedOrderV3Result result = wxPayService.unifiedPartnerOrderV3(TradeTypeEnum.JSAPI, request);
147+ * String prepayId = result.getPrepayId();
148+ * // 存储prepayId到数据库...
149+ *
150+ * // 步骤2:需要支付时,使用存储的prepay_id生成支付信息
151+ * WxPayUnifiedOrderV3Result.JsapiResult payInfo = WxPayUnifiedOrderV3Result.getJsapiPayInfo(
152+ * prepayId, appId, wxPayService.getConfig().getPrivateKey()
153+ * );
154+ * </pre>
155+ *
156+ * @param prepayId 预支付交易会话标识
157+ * @param appId 应用ID
158+ * @param privateKey 商户私钥,用于签名
159+ * @return JSAPI支付所需的参数对象
160+ */
161+ public static JsapiResult getJsapiPayInfo (String prepayId , String appId , PrivateKey privateKey ) {
162+ if (prepayId == null || appId == null || privateKey == null ) {
163+ throw new IllegalArgumentException ("prepayId, appId 和 privateKey 不能为空" );
164+ }
165+ return buildJsapiResult (prepayId , appId , privateKey );
166+ }
167+
168+ /**
169+ * <pre>
170+ * 根据已有的prepay_id生成APP支付所需的参数对象(解耦版本)
171+ * 应用场景:
172+ * 1. 用户已经通过createPartnerOrderV3或unifiedPartnerOrderV3获取了prepay_id
173+ * 2. 用户希望存储prepay_id用于后续复用
174+ * 3. 支付失败后,使用存储的prepay_id重新生成支付签名信息
175+ *
176+ * 使用示例:
177+ * // 步骤1:创建订单并获取prepay_id
178+ * WxPayUnifiedOrderV3Result result = wxPayService.unifiedPartnerOrderV3(TradeTypeEnum.APP, request);
179+ * String prepayId = result.getPrepayId();
180+ * // 存储prepayId到数据库...
181+ *
182+ * // 步骤2:需要支付时,使用存储的prepay_id生成支付信息
183+ * WxPayUnifiedOrderV3Result.AppResult payInfo = WxPayUnifiedOrderV3Result.getAppPayInfo(
184+ * prepayId, appId, mchId, wxPayService.getConfig().getPrivateKey()
185+ * );
186+ * </pre>
187+ *
188+ * @param prepayId 预支付交易会话标识
189+ * @param appId 应用ID
190+ * @param mchId 商户号
191+ * @param privateKey 商户私钥,用于签名
192+ * @return APP支付所需的参数对象
193+ */
194+ public static AppResult getAppPayInfo (String prepayId , String appId , String mchId , PrivateKey privateKey ) {
195+ if (prepayId == null || appId == null || mchId == null || privateKey == null ) {
196+ throw new IllegalArgumentException ("prepayId, appId, mchId 和 privateKey 不能为空" );
197+ }
198+ return buildAppResult (prepayId , appId , mchId , privateKey );
199+ }
200+
201+ /**
202+ * 构建JSAPI支付结果对象
203+ *
204+ * @param prepayId 预支付交易会话标识
205+ * @param appId 应用ID
206+ * @param privateKey 商户私钥,用于签名
207+ * @return JSAPI支付所需的参数对象
208+ */
209+ private static JsapiResult buildJsapiResult (String prepayId , String appId , PrivateKey privateKey ) {
210+ String timestamp = String .valueOf (System .currentTimeMillis () / 1000 );
211+ String nonceStr = SignUtils .genRandomStr ();
212+ JsapiResult jsapiResult = new JsapiResult ();
213+ jsapiResult .setAppId (appId ).setTimeStamp (timestamp )
214+ .setPackageValue ("prepay_id=" + prepayId ).setNonceStr (nonceStr )
215+ .setPrepayId (prepayId )
216+ //签名类型,默认为RSA,仅支持RSA。
217+ .setSignType ("RSA" ).setPaySign (SignUtils .sign (jsapiResult .getSignStr (), privateKey ));
218+ return jsapiResult ;
219+ }
220+
221+ /**
222+ * 构建APP支付结果对象
223+ *
224+ * @param prepayId 预支付交易会话标识
225+ * @param appId 应用ID
226+ * @param mchId 商户号
227+ * @param privateKey 商户私钥,用于签名
228+ * @return APP支付所需的参数对象
229+ */
230+ private static AppResult buildAppResult (String prepayId , String appId , String mchId , PrivateKey privateKey ) {
231+ String timestamp = String .valueOf (System .currentTimeMillis () / 1000 );
232+ String nonceStr = SignUtils .genRandomStr ();
233+ AppResult appResult = new AppResult ();
234+ appResult .setAppid (appId ).setPrepayId (prepayId ).setPartnerId (mchId )
235+ .setNoncestr (nonceStr ).setTimestamp (timestamp )
236+ //暂填写固定值Sign=WXPay
237+ .setPackageValue ("Sign=WXPay" )
238+ .setSign (SignUtils .sign (appResult .getSignStr (), privateKey ));
239+ return appResult ;
240+ }
135241}
0 commit comments