---
url: "https://pay.weixin.qq.com/doc/v3/partner/4012476113-java.md"
title: "申请资金出境-请求示例-java"
doc_id: 4012476113
example_lang: "java"
---

## Java


需配合微信支付工具库 WXPayUtility 使用，请参考 [Java](https://pay.weixin.qq.com/doc/v3/merchant/4014931831.md)

```
package com.java.demo;

import com.java.utils.WXPayUtility; // 引用微信支付工具库，参考：https://pay.weixin.qq.com/doc/v3/partner/4014985777

import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 申请资金出境
 */
public class CreateOrder {
  private static String HOST = "https://api.mch.weixin.qq.com";
  private static String METHOD = "POST";
  private static String PATH = "/v3/funds-to-oversea/orders";

  public static void main(String[] args) {
    // TODO: 请准备商户开发必要参数，参考：https://pay.weixin.qq.com/doc/v3/partner/4013080340
    CreateOrder client = new CreateOrder(
      "19xxxxxxxx",                    // 商户号，是由微信支付系统生成并分配给每个商户的唯一标识符，商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/partner/4013080340
      "1DDE55AD98Exxxxxxxxxx",         // 商户API证书序列号，如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924
      "/path/to/apiclient_key.pem",     // 商户API证书私钥文件路径，本地文件路径
      "PUB_KEY_ID_xxxxxxxxxxxxx",      // 微信支付公钥ID，如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589
      "/path/to/wxp_pub.pem"           // 微信支付公钥文件路径，本地文件路径
    );

    CreateOrderRequest request = new CreateOrderRequest();
    request.outOrderId = "merchant_1123123";
    request.subMchid = "123456";
    request.transactionId = "4208450740201411110007820472";
    request.amount = 10L;
    request.foreignCurrency = "USD";
    request.goodsInfo = new ArrayList<>();
    {
      GoodsInfo goodsInfoItem = new GoodsInfo();
      goodsInfoItem.goodsName = "橘子";
      goodsInfoItem.goodsCategory = "家用电器";
      goodsInfoItem.goodsUnitPrice = 1L;
      goodsInfoItem.goodsQuantity = 1L;
      request.goodsInfo.add(goodsInfoItem);
    };
    request.sellerInfo = new SellerInfo();
    request.sellerInfo.overseaBusinessName = "香港xxxx公司";
    request.sellerInfo.overseaShopName = "香港xxx公司xxx店铺";
    request.sellerInfo.sellerId = "id2123123123";
    request.expressInfo = new ExpressInfo();
    request.expressInfo.courierNumber = "curier_number_1231";
    request.expressInfo.expressCompanyName = "国际xxx物流";
    request.payeeInfo = new PayeeInfo();
    request.payeeInfo.payeeId = "ID123112312";
    request.presaleInfo = new PresaleInfo();
    request.presaleInfo.type = PresaleOrderType.DEPOSIT;
    request.presaleInfo.totalAmount = 10L;
    request.presaleInfo.depositTransactionId = "4208450740201411110007820472";
    request.presaleInfo.balanceTransactionId = "4208450740201411110007820472";
    try {
      Order response = client.run(request);
        // TODO: 请求成功，继续业务逻辑
        System.out.println(response);
    } catch (WXPayUtility.ApiException e) {
        // TODO: 请求失败，根据状态码执行不同的逻辑
        e.printStackTrace();
    }
  }

  public Order run(CreateOrderRequest request) {
    String uri = PATH;
    String reqBody = WXPayUtility.toJson(request);

    Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
    reqBuilder.addHeader("Accept", "application/json");
    reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
    reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
    reqBuilder.addHeader("Content-Type", "application/json");
    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
    reqBuilder.method(METHOD, requestBody);
    Request httpRequest = reqBuilder.build();

    // 发送HTTP请求
    OkHttpClient client = new OkHttpClient.Builder().build();
    try (Response httpResponse = client.newCall(httpRequest).execute()) {
      String respBody = WXPayUtility.extractBody(httpResponse);
      if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
        // 2XX 成功，验证应答签名
        WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
            httpResponse.headers(), respBody);

        // 从HTTP应答报文构建返回数据
        return WXPayUtility.fromJson(respBody, Order.class);
      } else {
        throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
      }
    } catch (IOException e) {
      throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
    }
  }

  private final String mchid;
  private final String certificateSerialNo;
  private final PrivateKey privateKey;
  private final String wechatPayPublicKeyId;
  private final PublicKey wechatPayPublicKey;

  public CreateOrder(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
    this.mchid = mchid;
    this.certificateSerialNo = certificateSerialNo;
    this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
    this.wechatPayPublicKeyId = wechatPayPublicKeyId;
    this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
  }

  public static class CreateOrderRequest {
    @SerializedName("out_order_id")
    public String outOrderId;

    @SerializedName("sub_mchid")
    public String subMchid;

    @SerializedName("transaction_id")
    public String transactionId;

    @SerializedName("amount")
    public Long amount;

    @SerializedName("foreign_currency")
    public String foreignCurrency;

    @SerializedName("goods_info")
    public List<GoodsInfo> goodsInfo;

    @SerializedName("seller_info")
    public SellerInfo sellerInfo;

    @SerializedName("express_info")
    public ExpressInfo expressInfo;

    @SerializedName("payee_info")
    public PayeeInfo payeeInfo;

    @SerializedName("presale_info")
    public PresaleInfo presaleInfo;
  }

  public static class Order {
    @SerializedName("out_order_id")
    public String outOrderId;

    @SerializedName("sub_mchid")
    public String subMchid;

    @SerializedName("order_id")
    public String orderId;

    @SerializedName("result")
    public String result;

    @SerializedName("fail_reason")
    public String failReason;

    @SerializedName("amount")
    public Long amount;

    @SerializedName("foreign_amount")
    public Long foreignAmount;

    @SerializedName("foreign_currency")
    public String foreignCurrency;

    @SerializedName("rate")
    public Long rate;

    @SerializedName("exchange_rate_time")
    public String exchangeRateTime;

    @SerializedName("estimate_exchange_rate_time")
    public String estimateExchangeRateTime;

    @SerializedName("departure_amount")
    public Long departureAmount;

    @SerializedName("fee")
    public Long fee;

    @SerializedName("charge_mchid")
    public String chargeMchid;

    @SerializedName("charge_account_type")
    public AccountType chargeAccountType;
  }

  public static class GoodsInfo {
    @SerializedName("goods_name")
    public String goodsName;

    @SerializedName("goods_category")
    public String goodsCategory;

    @SerializedName("goods_unit_price")
    public Long goodsUnitPrice;

    @SerializedName("goods_quantity")
    public Long goodsQuantity;
  }

  public static class SellerInfo {
    @SerializedName("oversea_business_name")
    public String overseaBusinessName;

    @SerializedName("oversea_shop_name")
    public String overseaShopName;

    @SerializedName("seller_id")
    public String sellerId;
  }

  public static class ExpressInfo {
    @SerializedName("courier_number")
    public String courierNumber;

    @SerializedName("express_company_name")
    public String expressCompanyName;
  }

  public static class PayeeInfo {
    @SerializedName("payee_id")
    public String payeeId;
  }

  public static class PresaleInfo {
    @SerializedName("type")
    public PresaleOrderType type;

    @SerializedName("total_amount")
    public Long totalAmount;

    @SerializedName("deposit_transaction_id")
    public String depositTransactionId;

    @SerializedName("balance_transaction_id")
    public String balanceTransactionId;
  }

  public enum AccountType {
    @SerializedName("BASIC")
    BASIC,
    @SerializedName("FEES")
    FEES
  }

  public enum PresaleOrderType {
    @SerializedName("DEPOSIT")
    DEPOSIT,
    @SerializedName("BALANCE")
    BALANCE
  }

}

```
