Skip to content

Commit

Permalink
feat: binarywang#3327【微信支付】平台收付通(注销申请)
Browse files Browse the repository at this point in the history
https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/cancel-applications/create-cancel-application.html
平台收付通(注销申请)-注销申请单-提交注销申请单
平台收付通(注销申请)-注销申请单-查询注销单状态
平台收付通(注销申请)-图片上传-图片上传

Closes binarywang#3327
  • Loading branch information
zhuangzibin committed Oct 9, 2024
1 parent 17399b5 commit cecdeaf
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.github.binarywang.wxpay.bean.ecommerce;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 图片上传API
* <pre>
* https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/media/upload-media.html
* </pre>
*/
@Data
@NoArgsConstructor
public class AccountCancelApplicationsMediaResult implements Serializable {

/**
* 微信返回的媒体文件标识ID。
*/
@SerializedName(value = "media_id")
private String mediaId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.github.binarywang.wxpay.bean.ecommerce;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

/**
* 提交注销申请单
* <pre>
* https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/cancel-applications/create-cancel-application.html
* </pre>
*/
@Data
@NoArgsConstructor
public class AccountCancelApplicationsRequest implements Serializable {

/**
* 【申请注销的二级商户号】 电商平台二级商户号,由微信支付生成并下发
*/
@SerializedName(value = "sub_mchid")
private String subMchid;

/**
* 【商户注销申请单号】 商户注销申请单号,由商户自定义生成,要求在服务商维度下是唯一的,必须仅包含大小写字母与数字
*/
@SerializedName(value = "out_apply_no")
private String outApplyNo;

/**
* 【注销申请材料】 注销申请材料,详见文档:注销申请材料
*/
@SerializedName(value = "application_info")
private List<CancelApplicationInfo> applicationInfo;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class CancelApplicationInfo implements Serializable {

/**
*【注销申请材料类型】 注销申请材料类型,详见文档:注销申请材料
* 可选取值:
* SP_MERCHANT_APPLICATION: 此枚举值已废弃,请使用新字段 SP_CANCEL_ACCOUNT_APPLICATION 以及新版本材料
* SUB_MERCHANT_APPLICATION: 此枚举值已废弃,请使用新字段 SUB_CANCEL_ACCOUNT_APPLICATION 以及新版本材料
* MISSING_OFFICIAL_SEAL_LETTER: 此材料已废弃,无需上传
* SP_CANCEL_ACCOUNT_APPLICATION: 电商服务商注销电商子申请书,请下载模板打印纸质版、填写盖章后拍照。模板文档详见:微信支付商户号注销申请书-服务商(纸质版)
* SUB_CANCEL_ACCOUNT_APPLICATION: 电商服务商子商户注销申请书,详见文档:微信支付商户号注销申请书-电商平台子商户适用(纸质版)
*/
@SerializedName("application_type")
private String applicationType;

/**
* 【注销申请材料照片ID】 注销申请材料照片ID,请填写通过上传图片接口预先上传图片生成好的media_id
*/
@SerializedName("application_media_id")
private String applicationMediaId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.github.binarywang.wxpay.bean.ecommerce;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
* 提交注销申请单
* <pre>
* https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/cancel-applications/create-cancel-application.html
* </pre>
*/
@Data
@NoArgsConstructor
public class AccountCancelApplicationsResult implements Serializable {

/**
* 【商户注销申请单号】 商户注销申请单号,原样返回请求参数里的内容
*/
@SerializedName(value = "out_apply_no")
private String outApplyNo;

/**
* 【二级商户号】 二级商户号
*/
@SerializedName(value = "sub_mchid")
private String subMchid;

/**
* 【驳回原因】 受理失败原因
*/
@SerializedName(value = "reject_reason")
private String rejectReason;

/**
* 【注销状态】 注销状态
* 可选取值:
* REVIEWING: 审核中
* REJECTED: 审核驳回,驳回原因详见reject_reason
* CANCEL_SUCCESS: 注销成功
*/
@SerializedName(value = "cancel_state")
private String cancelState;

/**
* 【最后更新时间】 最后更新时间。遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
*/
@SerializedName(value = "update_time")
private String updateTime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
Expand Down Expand Up @@ -535,4 +537,39 @@ public interface EcommerceService {
*/
SubsidiesCancelResult subsidiesCancel(SubsidiesCancelRequest subsidiesCancelRequest) throws WxPayException;

/**
* <pre>
* 提交注销申请单
* 文档地址: https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/cancel-applications/create-cancel-application.html
* </pre>
*
* @param accountCancelApplicationsRequest 提交注销申请单
* @return 返回数据 return AccountCancelApplicationsResult
* @throws WxPayException the wx pay exception
*/
AccountCancelApplicationsResult createdAccountCancelApplication(AccountCancelApplicationsRequest accountCancelApplicationsRequest) throws WxPayException;

/**
* <pre>
* 查询注销单状态
* 文档地址: https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/cancel-applications/get-cancel-application.html
* </pre>
*
* @param outApplyNo 注销申请单号
* @return 返回数据 return AccountCancelApplicationsResult
* @throws WxPayException the wx pay exception
*/
AccountCancelApplicationsResult getAccountCancelApplication(String outApplyNo) throws WxPayException;

/**
* <pre>
* 注销单资料图片上传
* 文档地址: https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/media/upload-media.html
* </pre>
*
* @param imageFile 图片
* @return 返回数据 return AccountCancelApplicationsResult
* @throws WxPayException the wx pay exception
*/
AccountCancelApplicationsMediaResult uploadMediaAccountCancelApplication(File imageFile) throws WxPayException, IOException;;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,27 @@
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.EcommerceService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.v3.WechatPayUploadHttpPost;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
import com.google.common.base.CaseFormat;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.RequiredArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.text.DateFormat;
Expand Down Expand Up @@ -395,6 +400,36 @@ public SubsidiesCancelResult subsidiesCancel(SubsidiesCancelRequest subsidiesCan
String response = this.payService.postV3(url, GSON.toJson(subsidiesCancelRequest));
return GSON.fromJson(response, SubsidiesCancelResult.class);
}

@Override
public AccountCancelApplicationsResult createdAccountCancelApplication(AccountCancelApplicationsRequest accountCancelApplicationsRequest) throws WxPayException {
String url = String.format("%s/v3/ecommerce/account/cancel-applications", this.payService.getPayBaseUrl());
String response = this.payService.postV3(url, GSON.toJson(accountCancelApplicationsRequest));
return GSON.fromJson(response, AccountCancelApplicationsResult.class);
}

@Override
public AccountCancelApplicationsResult getAccountCancelApplication(String outApplyNo) throws WxPayException {
String url = String.format("%s/v3/ecommerce/account/cancel-applications/out-apply-no/%s", this.payService.getPayBaseUrl(), outApplyNo);
String result = this.payService.getV3(url);
return GSON.fromJson(result, AccountCancelApplicationsResult.class);
}

@Override
public AccountCancelApplicationsMediaResult uploadMediaAccountCancelApplication(File imageFile) throws WxPayException, IOException {
String url = String.format("%s/v3/ecommerce/account/cancel-applications/media", this.payService.getPayBaseUrl());
try (FileInputStream s1 = new FileInputStream(imageFile)) {
String sha256 = DigestUtils.sha256Hex(s1);
try (InputStream s2 = new FileInputStream(imageFile)) {
WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url))
.withImage(imageFile.getName(), sha256, s2)
.buildEcommerceAccount();
String result = this.payService.postV3(url, request);
return GSON.fromJson(result, AccountCancelApplicationsMediaResult.class);
}
}
}

/**
* 校验通知签名
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,33 @@ public WechatPayUploadHttpPost build() {

return request;
}

/**
* 平台收付通(注销申请)-图片上传-图片上传
* https://pay.weixin.qq.com/docs/partner/apis/ecommerce-cancel/media/upload-media.html
* @return WechatPayUploadHttpPost
*/
public WechatPayUploadHttpPost buildEcommerceAccount() {
if (fileName == null || fileSha256 == null || fileInputStream == null) {
throw new IllegalArgumentException("缺少待上传图片文件信息");
}

if (uri == null) {
throw new IllegalArgumentException("缺少上传图片接口URL");
}

String meta = String.format("{\"file_name\":\"%s\",\"file_digest\":\"%s\"}", fileName, fileSha256);
WechatPayUploadHttpPost request = new WechatPayUploadHttpPost(uri, meta);

MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.RFC6532)
.addBinaryBody("file", fileInputStream, fileContentType, fileName)
.addTextBody("meta", meta, ContentType.APPLICATION_JSON);

request.setEntity(entityBuilder.build());
request.addHeader("Accept", ContentType.APPLICATION_JSON.toString());

return request;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package com.github.binarywang.wxpay.service.impl;
import com.google.common.collect.Lists;

import com.github.binarywang.wxpay.bean.ecommerce.CombineTransactionsRequest;
import com.github.binarywang.wxpay.bean.ecommerce.PartnerTransactionsQueryRequest;
import com.github.binarywang.wxpay.bean.ecommerce.PartnerTransactionsResult;
import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingReceiverRequest;
import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingReceiverResult;
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader;
import com.github.binarywang.wxpay.bean.ecommerce.TransactionsResult;
import com.github.binarywang.wxpay.bean.ecommerce.*;
import com.github.binarywang.wxpay.bean.ecommerce.enums.SpAccountTypeEnum;
import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
Expand All @@ -19,6 +14,8 @@
import org.testng.annotations.Guice;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

Expand Down Expand Up @@ -151,4 +148,29 @@ public void testSubDayEndBalance() throws WxPayException {
String date = "";
wxPayService.getEcommerceService().subDayEndBalance(subMchid, date);
}

@Test
public void testCreatedAccountCancelApplication() throws WxPayException {
AccountCancelApplicationsRequest request = new AccountCancelApplicationsRequest();
request.setSubMchid("");
request.setOutApplyNo("");
request.setApplicationInfo(Lists.newArrayList());

AccountCancelApplicationsResult result = wxPayService.getEcommerceService().createdAccountCancelApplication(request);
log.info("请求参数:{} 响应结果:{}", request, result);
}

@Test
public void testGetAccountCancelApplication() throws WxPayException {
String request = "申请单号";
AccountCancelApplicationsResult result = wxPayService.getEcommerceService().getAccountCancelApplication(request);
log.info("请求参数:{} 响应结果:{}", request, result);
}

@Test
public void testUploadMediaAccountCancelApplication() throws WxPayException, IOException {
AccountCancelApplicationsMediaResult result = wxPayService.getEcommerceService()
.uploadMediaAccountCancelApplication(new File("src\\test\\resources\\mm.jpeg"));
log.info("响应结果:{}", result);
}
}

0 comments on commit cecdeaf

Please sign in to comment.