🆕 #3618 【微信支付】增加境外微信支付的支持
This commit is contained in:
120
weixin-java-pay/OVERSEAS_PAY.md
Normal file
120
weixin-java-pay/OVERSEAS_PAY.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# 境外微信支付(Overseas WeChat Pay)支持
|
||||
|
||||
本次更新添加了境外微信支付的支持,解决了 [Issue #3618](https://github.com/binarywang/WxJava/issues/3618) 中提到的问题。
|
||||
|
||||
## 问题背景
|
||||
|
||||
境外微信支付需要使用新的API接口地址和额外的参数:
|
||||
- 使用不同的基础URL: `https://apihk.mch.weixin.qq.com`
|
||||
- 需要额外的参数: `trade_type` 和 `merchant_category_code`
|
||||
- 使用不同的API端点: `/global/v3/transactions/*`
|
||||
|
||||
## 新增功能
|
||||
|
||||
### 1. GlobalTradeTypeEnum
|
||||
新的枚举类,定义了境外支付的交易类型和对应的API端点:
|
||||
- `APP`: `/global/v3/transactions/app`
|
||||
- `JSAPI`: `/global/v3/transactions/jsapi`
|
||||
- `NATIVE`: `/global/v3/transactions/native`
|
||||
- `H5`: `/global/v3/transactions/h5`
|
||||
|
||||
### 2. WxPayUnifiedOrderV3GlobalRequest
|
||||
扩展的请求类,包含境外支付必需的额外字段:
|
||||
- `trade_type`: 交易类型 (JSAPI, APP, NATIVE, H5)
|
||||
- `merchant_category_code`: 商户类目代码(境外商户必填)
|
||||
|
||||
### 3. 新的服务方法
|
||||
- `createOrderV3Global()`: 创建境外支付订单
|
||||
- `unifiedOrderV3Global()`: 境外统一下单接口
|
||||
|
||||
## 使用示例
|
||||
|
||||
### JSAPI支付示例
|
||||
```java
|
||||
// 创建境外支付请求
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
request.setOutTradeNo(RandomUtils.getRandomStr());
|
||||
request.setDescription("境外商品购买");
|
||||
request.setNotifyUrl("https://your-domain.com/notify");
|
||||
|
||||
// 设置金额
|
||||
WxPayUnifiedOrderV3GlobalRequest.Amount amount = new WxPayUnifiedOrderV3GlobalRequest.Amount();
|
||||
amount.setCurrency(WxPayConstants.CurrencyType.CNY);
|
||||
amount.setTotal(100); // 1元,单位为分
|
||||
request.setAmount(amount);
|
||||
|
||||
// 设置支付者
|
||||
WxPayUnifiedOrderV3GlobalRequest.Payer payer = new WxPayUnifiedOrderV3GlobalRequest.Payer();
|
||||
payer.setOpenid("用户的openid");
|
||||
request.setPayer(payer);
|
||||
|
||||
// 设置境外支付必需的参数
|
||||
request.setTradeType("JSAPI");
|
||||
request.setMerchantCategoryCode("5812"); // 商户类目代码
|
||||
|
||||
// 调用境外支付接口
|
||||
WxPayUnifiedOrderV3Result.JsapiResult result = payService.createOrderV3Global(
|
||||
GlobalTradeTypeEnum.JSAPI,
|
||||
request
|
||||
);
|
||||
```
|
||||
|
||||
### APP支付示例
|
||||
```java
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
// ... 设置基础信息 ...
|
||||
|
||||
request.setTradeType("APP");
|
||||
request.setMerchantCategoryCode("5812");
|
||||
request.setPayer(new WxPayUnifiedOrderV3GlobalRequest.Payer()); // APP支付不需要openid
|
||||
|
||||
WxPayUnifiedOrderV3Result.AppResult result = payService.createOrderV3Global(
|
||||
GlobalTradeTypeEnum.APP,
|
||||
request
|
||||
);
|
||||
```
|
||||
|
||||
### NATIVE支付示例
|
||||
```java
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
// ... 设置基础信息 ...
|
||||
|
||||
request.setTradeType("NATIVE");
|
||||
request.setMerchantCategoryCode("5812");
|
||||
request.setPayer(new WxPayUnifiedOrderV3GlobalRequest.Payer());
|
||||
|
||||
String codeUrl = payService.createOrderV3Global(
|
||||
GlobalTradeTypeEnum.NATIVE,
|
||||
request
|
||||
);
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
境外支付使用相同的 `WxPayConfig` 配置,无需特殊设置:
|
||||
|
||||
```java
|
||||
WxPayConfig config = new WxPayConfig();
|
||||
config.setAppId("你的AppId");
|
||||
config.setMchId("你的境外商户号");
|
||||
config.setMchKey("你的商户密钥");
|
||||
config.setNotifyUrl("https://your-domain.com/notify");
|
||||
|
||||
// V3相关配置
|
||||
config.setPrivateKeyPath("你的私钥文件路径");
|
||||
config.setCertSerialNo("你的商户证书序列号");
|
||||
config.setApiV3Key("你的APIv3密钥");
|
||||
```
|
||||
|
||||
**注意**: 境外支付会自动使用 `https://apihk.mch.weixin.qq.com` 作为基础URL,无需手动设置。
|
||||
|
||||
## 兼容性
|
||||
|
||||
- 完全向后兼容,不影响现有的国内支付功能
|
||||
- 使用相同的配置类和结果类
|
||||
- 遵循现有的代码风格和架构模式
|
||||
|
||||
## 参考文档
|
||||
|
||||
- [境外微信支付文档](https://pay.weixin.qq.com/doc/global/v3/zh/4013014223)
|
||||
- [原始Issue #3618](https://github.com/binarywang/WxJava/issues/3618)
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.github.binarywang.wxpay.bean.request;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 境外微信支付统一下单请求参数对象.
|
||||
* 参考文档:https://pay.weixin.qq.com/doc/global/v3/zh/4013014223
|
||||
* </pre>
|
||||
*
|
||||
* @author Binary Wang
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class WxPayUnifiedOrderV3GlobalRequest extends WxPayUnifiedOrderV3Request implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 字段名:交易类型
|
||||
* 变量名:trade_type
|
||||
* 是否必填:是
|
||||
* 类型:string[1,16]
|
||||
* 描述:
|
||||
* 交易类型,取值如下:
|
||||
* JSAPI--JSAPI支付
|
||||
* NATIVE--Native支付
|
||||
* APP--APP支付
|
||||
* H5--H5支付
|
||||
* 示例值:JSAPI
|
||||
* </pre>
|
||||
*/
|
||||
@SerializedName(value = "trade_type")
|
||||
private String tradeType;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 字段名:商户类目
|
||||
* 变量名:merchant_category_code
|
||||
* 是否必填:是
|
||||
* 类型:string[1,32]
|
||||
* 描述:
|
||||
* 商户类目,境外商户必填
|
||||
* 示例值:5812
|
||||
* </pre>
|
||||
*/
|
||||
@SerializedName(value = "merchant_category_code")
|
||||
private String merchantCategoryCode;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.github.binarywang.wxpay.bean.result.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 境外微信支付方式
|
||||
* Overseas WeChat Pay trade types with global endpoints
|
||||
*
|
||||
* @author Binary Wang
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum GlobalTradeTypeEnum {
|
||||
/**
|
||||
* APP
|
||||
*/
|
||||
APP("/global/v3/transactions/app"),
|
||||
/**
|
||||
* JSAPI 或 小程序
|
||||
*/
|
||||
JSAPI("/global/v3/transactions/jsapi"),
|
||||
/**
|
||||
* NATIVE
|
||||
*/
|
||||
NATIVE("/global/v3/transactions/native"),
|
||||
/**
|
||||
* H5
|
||||
*/
|
||||
H5("/global/v3/transactions/h5");
|
||||
|
||||
/**
|
||||
* 境外下单url
|
||||
*/
|
||||
private final String url;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.github.binarywang.wxpay.bean.notify.*;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.GlobalTradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
@@ -640,6 +641,17 @@ public interface WxPayService {
|
||||
*/
|
||||
<T> T createPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 境外微信支付调用统一下单接口,并组装生成支付所需参数对象.
|
||||
*
|
||||
* @param <T> 请使用{@link WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @param tradeType the global trade type
|
||||
* @param request 境外统一下单请求参数
|
||||
* @return 返回 {@link WxPayUnifiedOrderV3Result}里的内部类或字段
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
<T> T createOrderV3Global(GlobalTradeTypeEnum tradeType, WxPayUnifiedOrderV3GlobalRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
|
||||
*
|
||||
@@ -660,6 +672,16 @@ public interface WxPayService {
|
||||
*/
|
||||
WxPayUnifiedOrderV3Result unifiedOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* 境外微信支付在发起支付前,需要调用统一下单接口,获取"预支付交易会话标识"
|
||||
*
|
||||
* @param tradeType the global trade type
|
||||
* @param request 境外请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置)
|
||||
* @return the wx pay unified order result
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
WxPayUnifiedOrderV3Result unifiedOrderV3Global(GlobalTradeTypeEnum tradeType, WxPayUnifiedOrderV3GlobalRequest request) throws WxPayException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 合单支付API(APP支付、JSAPI支付、H5支付、NATIVE支付).
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
|
||||
import com.github.binarywang.wxpay.bean.request.*;
|
||||
import com.github.binarywang.wxpay.bean.result.*;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.GlobalTradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfigHolder;
|
||||
@@ -746,6 +747,14 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
return result.getPayInfo(tradeType, appId, request.getSubMchId(), this.getConfig().getPrivateKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T createOrderV3Global(GlobalTradeTypeEnum tradeType, WxPayUnifiedOrderV3GlobalRequest request) throws WxPayException {
|
||||
WxPayUnifiedOrderV3Result result = this.unifiedOrderV3Global(tradeType, request);
|
||||
// Convert GlobalTradeTypeEnum to TradeTypeEnum for getPayInfo method
|
||||
TradeTypeEnum domesticTradeType = TradeTypeEnum.valueOf(tradeType.name());
|
||||
return result.getPayInfo(domesticTradeType, request.getAppid(), request.getMchid(), this.getConfig().getPrivateKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayUnifiedOrderV3Result unifiedPartnerOrderV3(TradeTypeEnum tradeType, WxPayPartnerUnifiedOrderV3Request request) throws WxPayException {
|
||||
if (StringUtils.isBlank(request.getSpAppid())) {
|
||||
@@ -790,6 +799,28 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
|
||||
return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxPayUnifiedOrderV3Result unifiedOrderV3Global(GlobalTradeTypeEnum tradeType, WxPayUnifiedOrderV3GlobalRequest request) throws WxPayException {
|
||||
if (StringUtils.isBlank(request.getAppid())) {
|
||||
request.setAppid(this.getConfig().getAppId());
|
||||
}
|
||||
if (StringUtils.isBlank(request.getMchid())) {
|
||||
request.setMchid(this.getConfig().getMchId());
|
||||
}
|
||||
if (StringUtils.isBlank(request.getNotifyUrl())) {
|
||||
request.setNotifyUrl(this.getConfig().getNotifyUrl());
|
||||
}
|
||||
if (StringUtils.isBlank(request.getTradeType())) {
|
||||
request.setTradeType(tradeType.name());
|
||||
}
|
||||
|
||||
// Use global WeChat Pay base URL for overseas payments
|
||||
String globalBaseUrl = "https://apihk.mch.weixin.qq.com";
|
||||
String url = globalBaseUrl + tradeType.getUrl();
|
||||
String response = this.postV3WithWechatpaySerial(url, GSON.toJson(request));
|
||||
return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombineTransactionsResult combine(TradeTypeEnum tradeType, CombineTransactionsRequest request) throws WxPayException {
|
||||
if (StringUtils.isBlank(request.getCombineAppid())) {
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3GlobalRequest;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.GlobalTradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import me.chanjar.weixin.common.util.RandomUtils;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/**
|
||||
* 境外微信支付测试类
|
||||
*
|
||||
* @author Binary Wang
|
||||
*/
|
||||
public class BaseWxPayServiceGlobalImplTest {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
|
||||
@Test
|
||||
public void testWxPayUnifiedOrderV3GlobalRequest() {
|
||||
// Test that the new request class has the required fields
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
|
||||
// Set basic order information
|
||||
String outTradeNo = RandomUtils.getRandomStr();
|
||||
request.setOutTradeNo(outTradeNo);
|
||||
request.setDescription("Test overseas payment");
|
||||
request.setNotifyUrl("https://api.example.com/notify");
|
||||
|
||||
// Set amount
|
||||
WxPayUnifiedOrderV3GlobalRequest.Amount amount = new WxPayUnifiedOrderV3GlobalRequest.Amount();
|
||||
amount.setCurrency(WxPayConstants.CurrencyType.CNY);
|
||||
amount.setTotal(100); // 1 yuan in cents
|
||||
request.setAmount(amount);
|
||||
|
||||
// Set payer
|
||||
WxPayUnifiedOrderV3GlobalRequest.Payer payer = new WxPayUnifiedOrderV3GlobalRequest.Payer();
|
||||
payer.setOpenid("test_openid");
|
||||
request.setPayer(payer);
|
||||
|
||||
// Set the new required fields for global payments
|
||||
request.setTradeType("JSAPI");
|
||||
request.setMerchantCategoryCode("5812"); // Example category code
|
||||
|
||||
// Assert that all fields are properly set
|
||||
assertNotNull(request.getTradeType());
|
||||
assertNotNull(request.getMerchantCategoryCode());
|
||||
assertEquals("JSAPI", request.getTradeType());
|
||||
assertEquals("5812", request.getMerchantCategoryCode());
|
||||
assertEquals(outTradeNo, request.getOutTradeNo());
|
||||
assertEquals("Test overseas payment", request.getDescription());
|
||||
assertEquals(100, request.getAmount().getTotal());
|
||||
assertEquals("test_openid", request.getPayer().getOpenid());
|
||||
|
||||
// Test JSON serialization contains the new fields
|
||||
String json = GSON.toJson(request);
|
||||
assertTrue(json.contains("trade_type"));
|
||||
assertTrue(json.contains("merchant_category_code"));
|
||||
assertTrue(json.contains("JSAPI"));
|
||||
assertTrue(json.contains("5812"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGlobalTradeTypeEnum() {
|
||||
// Test that all trade types have the correct global endpoints
|
||||
assertEquals("/global/v3/transactions/app", GlobalTradeTypeEnum.APP.getUrl());
|
||||
assertEquals("/global/v3/transactions/jsapi", GlobalTradeTypeEnum.JSAPI.getUrl());
|
||||
assertEquals("/global/v3/transactions/native", GlobalTradeTypeEnum.NATIVE.getUrl());
|
||||
assertEquals("/global/v3/transactions/h5", GlobalTradeTypeEnum.H5.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGlobalTradeTypeEnumValues() {
|
||||
// Test that we have all the main trade types
|
||||
GlobalTradeTypeEnum[] tradeTypes = GlobalTradeTypeEnum.values();
|
||||
assertEquals(4, tradeTypes.length);
|
||||
|
||||
// Test that we can convert between enum name and TradeTypeEnum
|
||||
for (GlobalTradeTypeEnum globalType : tradeTypes) {
|
||||
// This tests that the enum names match between Global and regular TradeTypeEnum
|
||||
String name = globalType.name();
|
||||
assertNotNull(name);
|
||||
assertTrue(name.equals("APP") || name.equals("JSAPI") || name.equals("NATIVE") || name.equals("H5"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.github.binarywang.wxpay.service.impl;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3GlobalRequest;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
|
||||
import com.github.binarywang.wxpay.bean.result.enums.GlobalTradeTypeEnum;
|
||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import me.chanjar.weixin.common.util.RandomUtils;
|
||||
|
||||
/**
|
||||
* 境外微信支付使用示例
|
||||
* Example usage for overseas WeChat Pay
|
||||
*
|
||||
* @author Binary Wang
|
||||
*/
|
||||
public class OverseasWxPayExample {
|
||||
|
||||
/**
|
||||
* 境外微信支付JSAPI下单示例
|
||||
* Example for overseas WeChat Pay JSAPI order creation
|
||||
*/
|
||||
public void createOverseasJsapiOrder(WxPayService payService) throws WxPayException {
|
||||
// 创建境外支付请求对象
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
|
||||
// 设置基础订单信息
|
||||
request.setOutTradeNo(RandomUtils.getRandomStr()); // 商户订单号
|
||||
request.setDescription("境外商品购买"); // 商品描述
|
||||
request.setNotifyUrl("https://your-domain.com/notify"); // 支付通知地址
|
||||
|
||||
// 设置金额信息
|
||||
WxPayUnifiedOrderV3GlobalRequest.Amount amount = new WxPayUnifiedOrderV3GlobalRequest.Amount();
|
||||
amount.setCurrency(WxPayConstants.CurrencyType.CNY); // 币种
|
||||
amount.setTotal(100); // 金额,单位为分
|
||||
request.setAmount(amount);
|
||||
|
||||
// 设置支付者信息
|
||||
WxPayUnifiedOrderV3GlobalRequest.Payer payer = new WxPayUnifiedOrderV3GlobalRequest.Payer();
|
||||
payer.setOpenid("用户的openid"); // 用户openid
|
||||
request.setPayer(payer);
|
||||
|
||||
// 设置境外支付必需的参数
|
||||
request.setTradeType("JSAPI"); // 交易类型
|
||||
request.setMerchantCategoryCode("5812"); // 商户类目代码,境外商户必填
|
||||
|
||||
// 可选:设置场景信息
|
||||
WxPayUnifiedOrderV3GlobalRequest.SceneInfo sceneInfo = new WxPayUnifiedOrderV3GlobalRequest.SceneInfo();
|
||||
sceneInfo.setPayerClientIp("用户IP地址");
|
||||
request.setSceneInfo(sceneInfo);
|
||||
|
||||
// 调用境外支付接口
|
||||
WxPayUnifiedOrderV3Result.JsapiResult result = payService.createOrderV3Global(
|
||||
GlobalTradeTypeEnum.JSAPI,
|
||||
request
|
||||
);
|
||||
|
||||
// 返回的result包含前端需要的支付参数
|
||||
System.out.println("支付参数:" + result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 境外微信支付APP下单示例
|
||||
* Example for overseas WeChat Pay APP order creation
|
||||
*/
|
||||
public void createOverseasAppOrder(WxPayService payService) throws WxPayException {
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
|
||||
// 设置基础信息
|
||||
request.setOutTradeNo(RandomUtils.getRandomStr());
|
||||
request.setDescription("境外APP商品购买");
|
||||
request.setNotifyUrl("https://your-domain.com/notify");
|
||||
|
||||
// 设置金额
|
||||
WxPayUnifiedOrderV3GlobalRequest.Amount amount = new WxPayUnifiedOrderV3GlobalRequest.Amount();
|
||||
amount.setCurrency(WxPayConstants.CurrencyType.CNY);
|
||||
amount.setTotal(200); // 2元
|
||||
request.setAmount(amount);
|
||||
|
||||
// APP支付不需要设置payer.openid,但需要设置空的payer对象
|
||||
request.setPayer(new WxPayUnifiedOrderV3GlobalRequest.Payer());
|
||||
|
||||
// 境外支付必需参数
|
||||
request.setTradeType("APP");
|
||||
request.setMerchantCategoryCode("5812");
|
||||
|
||||
// 调用境外APP支付接口
|
||||
WxPayUnifiedOrderV3Result.AppResult result = payService.createOrderV3Global(
|
||||
GlobalTradeTypeEnum.APP,
|
||||
request
|
||||
);
|
||||
|
||||
System.out.println("APP支付参数:" + result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 境外微信支付NATIVE下单示例
|
||||
* Example for overseas WeChat Pay NATIVE order creation
|
||||
*/
|
||||
public void createOverseasNativeOrder(WxPayService payService) throws WxPayException {
|
||||
WxPayUnifiedOrderV3GlobalRequest request = new WxPayUnifiedOrderV3GlobalRequest();
|
||||
|
||||
request.setOutTradeNo(RandomUtils.getRandomStr());
|
||||
request.setDescription("境外扫码支付");
|
||||
request.setNotifyUrl("https://your-domain.com/notify");
|
||||
|
||||
// 设置金额
|
||||
WxPayUnifiedOrderV3GlobalRequest.Amount amount = new WxPayUnifiedOrderV3GlobalRequest.Amount();
|
||||
amount.setCurrency(WxPayConstants.CurrencyType.CNY);
|
||||
amount.setTotal(300); // 3元
|
||||
request.setAmount(amount);
|
||||
|
||||
// NATIVE支付不需要设置payer.openid
|
||||
request.setPayer(new WxPayUnifiedOrderV3GlobalRequest.Payer());
|
||||
|
||||
// 境外支付必需参数
|
||||
request.setTradeType("NATIVE");
|
||||
request.setMerchantCategoryCode("5812");
|
||||
|
||||
// 调用境外NATIVE支付接口
|
||||
String result = payService.createOrderV3Global(
|
||||
GlobalTradeTypeEnum.NATIVE,
|
||||
request
|
||||
);
|
||||
|
||||
System.out.println("NATIVE支付二维码链接:" + result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置示例
|
||||
* Configuration example
|
||||
*/
|
||||
public WxPayConfig createOverseasConfig() {
|
||||
WxPayConfig config = new WxPayConfig();
|
||||
|
||||
// 基础配置
|
||||
config.setAppId("你的AppId");
|
||||
config.setMchId("你的境外商户号");
|
||||
config.setMchKey("你的商户密钥");
|
||||
config.setNotifyUrl("https://your-domain.com/notify");
|
||||
|
||||
// 境外支付使用的是全球API,在代码中会自动使用 https://apihk.mch.weixin.qq.com 作为基础URL
|
||||
// 无需额外设置payBaseUrl,方法内部会自动处理
|
||||
|
||||
// V3相关配置(境外支付也使用V3接口)
|
||||
config.setPrivateKeyPath("你的私钥文件路径");
|
||||
config.setCertSerialNo("你的商户证书序列号");
|
||||
config.setApiV3Key("你的APIv3密钥");
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user