diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java new file mode 100644 index 000000000..92e069f63 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsRequest.java @@ -0,0 +1,796 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + + +/** + *
+ * 电商平台,可使用该接口,帮助其二级商户进件成为微信支付商户。 + * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml + *+ */ +@Data +@NoArgsConstructor +public class ApplymentsRequest implements Serializable { + /** + *
+ * 字段名:业务申请编号 + * 变量名:out_request_no + * 是否必填:是 + * 类型:string(124) + * 描述: + * 1、服务商自定义的商户唯一编号。 + * 2、每个编号对应一个申请单,每个申请单审核通过后会生成一个微信支付商户号。 + * 3、若申请单被驳回,可填写相同的“业务申请编号”,即可覆盖修改原申请单信息 。 + * 示例值:APPLYMENT_00000000001 + *+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; + + /** + *
+ * 字段名:主体类型 + * 变量名:organization_type + * 是否必填:是 + * 类型:string(4) + * 描述: + * 枚举值: + * 2401:小微商户,指无营业执照的商户。 + * 4:个体工商户,营业执照上的主体类型一般为个体户、个体工商户、个体经营。 + * 2:企业,营业执照上的主体类型一般为有限公司、有限责任公司。 + * 3:党政、机关及事业单位,包括国内各级、各类政府机构、事业单位等(如:公安、党团、司法、交通、旅游、工商税务、市政、医疗、教育、学校等机构)。 + * 1708:其他组织,不属于企业、政府/事业单位的组织机构(如社会团体、民办非企业、基金会),要求机构已办理组织机构代码证。 + * 示例值:2401 + *+ */ + @SerializedName(value = "organization_type") + private String organizationType; + + /** + *
+ * 字段名:+营业执照/登记证书信息 + * 变量名:business_license_info + * 是否必填:条件选填 + * 类型:object + * 描述: + * 1、主体为“小微”时,不填。 + * 2、主体为“个体工商户/企业”时,请上传营业执照。 + * 3、主体为“党政、机关及事业单位/其他组织”时,请上传登记证书。 + *+ */ + @SerializedName(value = "business_license_info") + private BusinessLicenseInfo businessLicenseInfo; + + /** + *
+ * 字段名:+组织机构代码证信息 + * 变量名:organization_cert_info + * 是否必填:条件选填 + * 类型:object + * 描述:主体为企业/党政、机关及事业单位/其他组织,且证件号码不是18位时必填。 + *+ */ + @SerializedName(value = "organization_cert_info") + private OrganizationCertInfo organizationCertInfo; + + /** + *
+ * 字段名:经营者/法人证件类型 + * 变量名:id_doc_type + * 是否必填:否 + * 类型:string(64) + * 描述: + * 1、主体为“小微”,只可选择:身份证。 + * 2、主体为“个体户/企业/党政、机关及事业单位/其他组织”,可选择:任一证件类型。 + * 3、若没有填写,系统默认选择:身份证。 + * 枚举值: + * IDENTIFICATION_TYPE_MAINLAND_IDCARD:中国大陆居民-身份证 + * IDENTIFICATION_TYPE_OVERSEA_PASSPORT:其他国家或地区居民-护照 + * IDENTIFICATION_TYPE_HONGKONG:中国香港居民–来往内地通行证 + * IDENTIFICATION_TYPE_MACAO:中国澳门居民–来往内地通行证 + * IDENTIFICATION_TYPE_TAIWAN:中国台湾居民–来往大陆通行证 + * 示例值:IDENTIFICATION_TYPE_MACAO + *+ */ + @SerializedName(value = "id_doc_type") + private String idDocType; + + /** + *
+ * 字段名:+经营者/法人身份证信息 + * 变量名:id_card_info + * 是否必填:条件选填 + * 类型:object + * 描述: + * 请填写经营者/法人的身份证信息 + * 证件类型为“身份证”时填写。 + * + *+ */ + @SerializedName(value = "id_card_info") + @SpecEncrypt + private IdCardInfo idCardInfo; + + /** + *
+ * 字段名:+经营者/法人其他类型证件信息 + * 变量名:id_doc_info + * 是否必填:条件选填 + * 类型:object + * 描述:证件类型为“来往内地通行证、来往大陆通行证、护照”时填写。 + *+ */ + @SerializedName(value = "id_doc_info") + private IdDocInfo idDocInfo; + + /** + *
+ * 字段名:是否填写结算账户信息 + * 变量名:need_account_info + * 是否必填:是 + * 类型:bool + * 描述: + * 可根据实际情况,填写“true”或“false”。 + * 1、若为“true”,则需填写结算账户信息。 + * 2、若为“false”,则无需填写结算账户信息。 + * 示例值:true + *+ */ + @SerializedName(value = "need_account_info") + private Boolean needAccountInfo; + + /** + *
+ * 字段名:+结算账户信息 + * 变量名:account_info + * 是否必填:条件选填 + * 类型:object + * 描述:若"是否填写结算账户信息"填写为“true”, 则必填,填写为“false”不填 。 + *+ */ + @SerializedName(value = "account_info") + @SpecEncrypt + private AccountInfo accountInfo; + + /** + *
+ * 字段名:+超级管理员信息 + * 变量名:contact_info + * 是否必填:是 + * 类型:object + * 描述: + * 请填写店铺的超级管理员信息。 + * 超级管理员需在开户后进行签约,并可接收日常重要管理信息和进行资金操作,请确定其为商户法定代表人或负责人。 + *+ */ + @SerializedName(value = "contact_info") + @SpecEncrypt + private ContactInfo contactInfo; + + /** + *
+ * 字段名:+店铺信息 + * 变量名:sales_scene_info + * 是否必填:是 + * 类型:object + * 描述:请填写店铺信息 + *+ */ + @SerializedName(value = "sales_scene_info") + private SalesSceneInfo salesSceneInfo; + + /** + *
+ * 字段名:商户简称 + * 变量名:merchant_shortname + * 是否必填:是 + * 类型:string(64) + * 描述: + * UTF-8格式,中文占3个字节,即最多16个汉字长度。将在支付完成页向买家展示,需与商家的实际售卖商品相符 。 + * 示例值:腾讯 + *+ */ + @SerializedName(value = "merchant_shortname") + private String merchantShortname; + + /** + *
+ * 字段名:特殊资质 + * 变量名:qualifications + * 是否必填:否 + * 类型:string(1024) + * 描述: + * 1、若店铺业务包含互联网售药,则需上传特殊资质-《互联网药品交易服务证》。 + * 2、最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 + * 示例值:[\"jTpGmxUX3FBWVQ5NJInE4d2I6_H7I4\"] + *+ */ + @SerializedName(value = "qualifications") + private String qualifications; + + /** + *
+ * 字段名:补充材料 + * 变量名:business_addition_pics + * 是否必填:否 + * 类型:string(1024) + * 描述: + * 最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 + * 示例值:[\"jTpGmg05InE4d2I6_H7I4\"] + *+ */ + @SerializedName(value = "business_addition_pics") + private String businessAdditionPics; + + /** + *
+ * 字段名:补充说明 + * 变量名:business_addition_desc + * 是否必填:否 + * 类型:string(256) + * 描述: + * 可填写512字以内 。 + * 示例值:特殊情况,说明原因 + *+ */ + @SerializedName(value = "business_addition_desc") + private String businessAdditionDesc; + + @Data + @NoArgsConstructor + public static class BusinessLicenseInfo implements Serializable{ + /** + *
+ * 字段名:证件扫描件 + * 变量名:business_license_copy + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、主体为“个体工商户/企业”时,请上传营业执照的证件图片。 + * 2、主体为“党政、机关及事业单位/其他组织”时,请上传登记证书的证件图片。 + * 3、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 + * 4、图片要求: + * (1)请上传证件的彩色扫描件或彩色数码拍摄件,黑白复印件需加盖公章(公章信息需完整) 。 + * (2)不得添加无关水印(非微信支付商户申请用途的其他水印)。 + * (3)需提供证件的正面拍摄件,完整、照面信息清晰可见。信息不清晰、扭曲、压缩变形、反光、不完整均不接受。 + * (4)不接受二次剪裁、翻拍、PS的证件照片。 + * 示例值: 47ZC6GC-vnrbEny__Ie_An5-tCpqxucuxi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 + *+ */ + @SerializedName(value = "business_license_copy") + private String businessLicenseCopy; + + /** + *
+ * 字段名:证件注册号 + * 变量名:business_license_number + * 是否必填:是 + * 类型:string(18) + * 描述: + * 1、主体为“个体工商户/企业”时,请填写营业执照上的注册号/统一社会信用代码,须为15位数字或 18位数字|大写字母。 + * 2、主体为“党政、机关及事业单位/其他组织”时,请填写登记证书的证书编号。 + * 示例值:123456789012345678 + * 特殊规则:长度最小15个字节 + *+ */ + @SerializedName(value = "business_license_number") + private String businessLicenseNumber; + + /** + *
+ * 字段名:商户名称 + * 变量名:merchant_name + * 是否必填:是 + * 类型:string(128) + * 描述: + * 1、请填写营业执照/登记证书的商家名称,2~110个字符,支持括号 。 + * 2、个体工商户/党政、机关及事业单位,不能以“公司”结尾。 + * 3、个体工商户,若营业执照上商户名称为空或为“无”,请填写"个体户+经营者姓名",如“个体户张三” 。 + * 示例值:腾讯科技有限公司 + *+ */ + @SerializedName(value = "merchant_name") + private String merchantName; + + /** + *
+ * 字段名:经营者/法定代表人姓名 + * 变量名:legal_person + * 是否必填:是 + * 类型:string(128) + * 描述: + * 请填写证件的经营者/法定代表人姓名 + * 示例值:张三 + *+ */ + @SerializedName(value = "legal_person") + private String legalPerson; + + /** + *
+ * 字段名:注册地址 + * 变量名:company_address + * 是否必填:条件选填 + * 类型:string(128) + * 描述: + * 主体为“党政、机关及事业单位/其他组织”时必填,请填写登记证书的注册地址。 + * 示例值:深圳南山区科苑路 + *+ */ + @SerializedName(value = "company_address") + private String companyAddress; + + /** + *
+ * 字段名:营业期限 + * 变量名:business_time + * 是否必填:条件选填 + * 类型:string(256) + * 描述: + * 1、主体为“党政、机关及事业单位/其他组织”时必填,请填写证件有效期。 + * 2、若证件有效期为长期,请填写:长期。 + * 3、结束时间需大于开始时间。 + * 4、有效期必须大于60天,即结束时间距当前时间需超过60天。 + * 示例值:[\"2014-01-01\",\"长期\"] + *+ */ + @SerializedName(value = "business_time") + private String businessTime; + + } + + @Data + @NoArgsConstructor + public static class OrganizationCertInfo implements Serializable { + /** + *
+ * 字段名:组织机构代码证照片 + * 变量名:organization_copy + * 是否必填:是 + * 类型:string(256) + * 描述: + * 可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。 + * 示例值:vByf3Gjm7KE53JXv\prrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 + *+ */ + @SerializedName(value = "organization_copy") + private String organizationCopy; + + /** + *
+ * 字段名:组织机构代码 + * 变量名:organization_number + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、请填写组织机构代码证上的组织机构代码。 + * 2、可填写9或10位 数字|字母|连字符。 + * 示例值:12345679-A + *+ */ + @SerializedName(value = "organization_number") + private String organizationNumber; + + /** + *
+ * 字段名:组织机构代码有效期限 + * 变量名:organization_time + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、请填写组织机构代码证的有效期限,注意参照示例中的格式。 + * 2、若证件有效期为长期,请填写:长期。 + * 3、结束时间需大于开始时间。 + * 4、有效期必须大于60天,即结束时间距当前时间需超过60天。 + * 示例值:[\"2014-01-01\",\"长期\"] + *+ */ + @SerializedName(value = "organization_time") + private String organizationTime; + + } + + @Data + @NoArgsConstructor + public static class IdCardInfo implements Serializable { + /** + *
+ * 字段名:身份证人像面照片 + * 变量名:id_card_copy + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、请上传经营者/法定代表人的身份证人像面照片。 + * 2、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。 + * 示例值:xpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ + *+ */ + @SerializedName(value = "id_card_copy") + private String idCardCopy; + + /** + *
+ * 字段名:身份证国徽面照片 + * 变量名:id_card_national + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、请上传经营者/法定代表人的身份证国徽面照片。 + * 2、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID 。 + * 示例值:vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 + *+ */ + @SerializedName(value = "id_card_national") + private String idCardNational; + + /** + *
+ * 字段名:身份证姓名 + * 变量名:id_card_name + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、请填写经营者/法定代表人对应身份证的姓名,2~30个中文字符、英文字符、符号。 + * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值:pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg== + * 字段加密:使用APIv3定义的方式加密 + *+ */ + @SerializedName(value = "id_card_name") + @SpecEncrypt + private String idCardName; + + /** + *
+ * 字段名:身份证号码 + * 变量名:id_card_number + * 是否必填:是 + * 类型:string(18) + * 描述: + * 1、请填写经营者/法定代表人对应身份证的号码。 + * 2、15位数字或17位数字+1位数字|X ,该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值:zV+BEmytMNQCqQ8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw==4 + * 特殊规则:长度最小15个字节 + *+ */ + @SerializedName(value = "id_card_number") + @SpecEncrypt + private String idCardNumber; + + /** + *
+ * 字段名:身份证有效期限 + * 变量名:id_card_valid_time + * 是否必填:是 + * 类型:string(128) + * 描述: + * 1、请填写身份证有效期的结束时间,注意参照示例中的格式。 + * 2、若证件有效期为长期,请填写:长期。 + * 3、证件有效期需大于60天。 + * 示例值:2026-06-06,长期 + *+ */ + @SerializedName(value = "id_card_valid_time") + private String idCardValidTime; + + } + + @Data + @NoArgsConstructor + public static class IdDocInfo implements Serializable { + /** + *
+ * 字段名:证件姓名 + * 变量名:id_doc_name + * 是否必填:是 + * 类型:string(128) + * 描述: + * 请填写经营者/法人姓名。 + * 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4LC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ + *+ */ + @SerializedName(value = "id_doc_name") + private String idDocName; + + /** + *
+ * 字段名:证件号码 + * 变量名:id_doc_number + * 是否必填:是 + * 类型:string(128) + * 描述: + * 7~11位 数字|字母|连字符 。 + * 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_go0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ + *+ */ + @SerializedName(value = "id_doc_number") + private String idDocNumber; + + /** + *
+ * 字段名:证件照片 + * 变量名:id_doc_copy + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。 + * 2、2M内的彩色图片,格式可为bmp、png、jpeg、jpg或gif 。 + * 示例值:xi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4 + *+ */ + @SerializedName(value = "id_doc_copy") + private String idDocCopy; + + /** + *
+ * 字段名:证件结束日期 + * 变量名:doc_period_end + * 是否必填:是 + * 类型:string(128) + * 描述: + * 1、请按照示例值填写。 + * 2、若证件有效期为长期,请填写:长期。 + * 3、证件有效期需大于60天 。 + * 示例值:2020-01-02 + *+ */ + @SerializedName(value = "doc_period_end") + private String docPeriodEnd; + + } + + @Data + @NoArgsConstructor + public static class AccountInfo implements Serializable { + /** + *
+ * 字段名:账户类型 + * 变量名:bank_account_type + * 是否必填:是 + * 类型:string(2) + * 描述: + * 1、若主体为企业/党政、机关及事业单位/其他组织,可填写:74-对公账户。 + * 2、若主体为小微,可填写:75-对私账户。 + * 3、若主体为个体工商户,可填写:74-对公账户或75-对私账户。 + * 示例值:75 + *+ */ + @SerializedName(value = "bank_account_type") + private String bankAccountType; + + /** + *
+ * 字段名:开户银行 + * 变量名:account_bank + * 是否必填:是 + * 类型:string(10) + * 描述: + * 详细参见开户银行对照表。 + * 示例值:工商银行 + *+ */ + @SerializedName(value = "account_bank") + private String accountBank; + + /** + *
+ * 字段名:开户名称 + * 变量名:account_name + * 是否必填:是 + * 类型:string(128) + * 描述: + * 1、选择经营者个人银行卡时,开户名称必须与身份证姓名一致。 + * 2、选择对公账户时,开户名称必须与营业执照上的“商户名称”一致。 + * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值:AOZdYGISxo4yw96uY1Pk7Rq79Jtt7+I8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw== + *+ */ + @SerializedName(value = "account_name") + @SpecEncrypt + private String accountName; + + /** + *
+ * 字段名:开户银行省市编码 + * 变量名:bank_address_code + * 是否必填:是 + * 类型:string(12) + * 描述: + * 至少精确到市,详细参见省市区编号对照表。 + * 示例值:110000 + *+ */ + @SerializedName(value = "bank_address_code") + private String bankAddressCode; + + /** + *
+ * 字段名:开户银行联行号 + * 变量名:bank_branch_id + * 是否必填:条件选填 + * 类型:string(64) + * 描述: + * 1、17家直连银行无需填写,如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。 + * 2、详细参见开户银行全称(含支行)对照表。 + * 示例值:402713354941 + *+ */ + @SerializedName(value = "bank_branch_id") + private String bankBranchId; + + /** + *
+ * 字段名:开户银行全称 (含支行) + * 变量名:bank_name + * 是否必填:条件选填 + * 类型:string(128) + * 描述: + * 1、17家直连银行无需填写,如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。 + * 2、需填写银行全称,如"深圳农村商业银行XXX支行" 。 + * 3、详细参见开户银行全称(含支行)对照表。 + * 示例值:施秉县农村信用合作联社城关信用社 + *+ */ + @SerializedName(value = "bank_name") + private String bankName; + + /** + *
+ * 字段名:银行帐号 + * 变量名:account_number + * 是否必填:是 + * 类型:string(128) + * 描述: + * 1、数字,长度遵循系统支持的对公/对私卡号长度要求表。 + * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值: d+xT+MQCvrLHUVDWv/8MR/dB7TkXLVfSrUxMPZy6jWWYzpRrEEaYQE8ZRGYoeorwC+w== + *+ */ + @SerializedName(value = "account_number") + @SpecEncrypt + private String accountNumber; + + } + + @Data + @NoArgsConstructor + public static class ContactInfo implements Serializable { + /** + *
+ * 字段名:超级管理员类型 + * 变量名:contact_type + * 是否必填:是 + * 类型:string(2) + * 描述: + * 1、小微商户,选择:65-法人/经营者。 + * 2、个体工商户/企业/党政、机关及事业单位/其他组织,可选择:65-法人/经营者、66- 负责人。 (负责人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。 + * 示例值:65 + *+ */ + @SerializedName(value = "contact_type") + private String contactType; + + /** + *
+ * 字段名:超级管理员姓名 + * 变量名:contact_name + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、若管理员类型为“法人”,则该姓名需与法人身份证姓名一致。 + * 2、若管理员类型为“经办人”,则可填写实际经办人的姓名。 + * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * (后续该管理员需使用实名微信号完成签约) + * 示例值: pVd1HJ6zyvPedzGaV+X3IdGdbDnuC4Eelw/wDa4SzfeespQO/0kjiwfqdfg== + *+ */ + @SerializedName(value = "contact_name") + @SpecEncrypt + private String contactName; + + /** + *
+ * 字段名:超级管理员身份证件号码 + * 变量名:contact_id_card_number + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、若管理员类型为法人,则该身份证号码需与法人身份证号码一致。若管理员类型为经办人,则可填写实际经办人的身份证号码。 + * 2、可传身份证、来往内地通行证、来往大陆通行证、护照等证件号码。 + * 3、超级管理员签约时,校验微信号绑定的银行卡实名信息,是否与该证件号码一致。 + * 4、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值:pVd1HJ6zmty7/mYNxLMpRSvMRtelw/wDa4SzfeespQO/0kjiwfqdfg== + *+ */ + @SerializedName(value = "contact_id_card_number") + @SpecEncrypt + private String contactIdCardNumber; + + /** + *
+ * 字段名:超级管理员手机 + * 变量名:mobile_phone + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、请填写管理员的手机号,11位数字, 用于接收微信支付的重要管理信息及日常操作验证码 。 + * 2、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+F6mfjbzQIzfb3HHLEjZ4YiNWWNeespQO/0kjiwfqdfg== + *+ */ + @SerializedName(value = "mobile_phone") + @SpecEncrypt + private String mobilePhone; + + /** + *
+ * 字段名:超级管理员邮箱 + * 变量名:contact_email + * 是否必填:是 + * 类型:string(256) + * 描述: + * 1、用于接收微信支付的开户邮件及日常业务通知。 + * 2、需要带@,遵循邮箱格式校验 。 + * 3、该字段需进行加密处理,加密方法详见敏感信息加密说明。 + * 示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+FWWNUlw/wDa4SzfeespQO/0kjiwfqdfg== + *+ */ + @SerializedName(value = "contact_email") + @SpecEncrypt + private String contactEmail; + + } + + @Data + @NoArgsConstructor + public static class SalesSceneInfo implements Serializable { + /** + *
+ * 字段名:店铺名称 + * 变量名:store_name + * 是否必填:是 + * 类型:string(256) + * 描述: + * 请填写店铺全称。 + * 示例值:爱烧烤 + *+ */ + @SerializedName(value = "store_name") + private String storeName; + + /** + *
+ * 字段名:店铺链接 + * 变量名:store_url + * 是否必填:二选一 + * 类型:string(1024) + * 描述: + * 1、店铺二维码or店铺链接二选一必填。 + * 2、请填写店铺主页链接,需符合网站规范。 + * 示例值:http://www.qq.com + *+ */ + @SerializedName(value = "store_url") + private String storeUrl; + + /** + *
+ * 字段名:店铺二维码 + * 变量名:store_qr_code + * 是否必填:1、店铺二维码 or 店铺链接二选一必填。 2、若为电商小程序,可上传店铺页面的小程序二维码。 3、请填写通过图片上传接口预先上传图片生成好的MediaID,仅能上传1张图片 。 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO1D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ + * 类型:string(256) + * 描述: + *+ */ + @SerializedName(value = "store_qr_code") + private String storeQrCode; + + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsResult.java new file mode 100644 index 000000000..dd2d46122 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsResult.java @@ -0,0 +1,43 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 二级商户进件 提交申请结果响应 + */ +@Data +@NoArgsConstructor +public class ApplymentsResult implements Serializable { + + /** + *
+ * 字段名:微信支付申请单号 + * 变量名:applyment_id + * 是否必填:是 + * 类型:uint64 + * 描述: + * 微信支付分配的申请单号 。 + * 示例值:2000002124775691 + *+ */ + @SerializedName(value = "applyment_id") + private String applymentId; + + /** + *
+ * 字段名:业务申请编号 + * 变量名:out_request_no + * 是否必填:是 + * 类型:string(124) + * 描述: + * 服务商自定义的商户唯一编号。每个编号对应一个申请单,每个申请单审核通过后会生成一个微信支付商户号。 + * 示例值:APPLYMENT_00000000001 + *+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsStatusResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsStatusResult.java new file mode 100644 index 000000000..00967cfa6 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/ecommerce/ApplymentsStatusResult.java @@ -0,0 +1,308 @@ +package com.github.binarywang.wxpay.bean.ecommerce; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@Data +@NoArgsConstructor +public class ApplymentsStatusResult implements Serializable { + /** + *
+ * 字段名:申请状态 + * 变量名:applyment_state + * 是否必填:否 + * 类型:string(32) + * 描述: + * 枚举值: + * CHECKING:资料校验中 + * ACCOUNT_NEED_VERIFY:待账户验证 + * AUDITING:审核中 + * REJECTED:已驳回 + * NEED_SIGN:待签约 + * FINISH:完成 + * FROZEN:已冻结 + * 示例值:FINISH + *+ */ + @SerializedName(value = "applyment_state") + private String applymentState; + + /** + *
+ * 字段名:申请状态描述 + * 变量名:applyment_state_desc + * 是否必填:否 + * 类型:string(32) + * 描述: + * 申请状态描述 + * 示例值:“审核中” + *+ */ + @SerializedName(value = "applyment_state_desc") + private String applymentStateDesc; + + /** + *
+ * 字段名:签约链接 + * 变量名:sign_url + * 是否必填:否 + * 类型:string(256) + * 描述: + * 1、当申请状态为NEED_SIGN时才返回。 + * 2、建议将链接转为二维码展示,需让申请单-管理者用微信扫码打开,完成签约。 + * 示例值:https://pay.weixin.qq.com/public/apply4ec_sign/s?applymentId=2000002126198476&sign=b207b673049a32c858f3aabd7d27c7ec + *+ */ + @SerializedName(value = "sign_url") + private String signUrl; + + /** + *
+ * 字段名:电商平台二级商户号 + * 变量名:sub_mchid + * 是否必填:否 + * 类型:string(32) + * 描述: + * 当申请状态为NEED_SIGN或FINISH时才返回。 + * 示例值:1542488631 + *+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+ * 字段名:+汇款账户验证信息 + * 变量名:account_validation + * 是否必填:否 + * 类型:object + * 描述:当申请状态为ACCOUNT_NEED_VERIFY 时有返回,可根据指引汇款,完成账户验证。 + *+ */ + @SerializedName(value = "account_validation") + private AccountValidation accountValidation; + + /** + *
+ * 字段名:+驳回原因详情 + * 变量名:audit_detail + * 是否必填:否 + * 类型:array + * 描述:各项资料的审核情况。当申请状态为REJECTED或 FROZEN时才返回。 + *+ */ + @SerializedName(value = "audit_detail") + private List
+ * 字段名:法人验证链接 + * 变量名:legal_validation_url + * 是否必填:否 + * 类型:string(256) + * 描述: + * 1、当申请状态为 + * ACCOUNT_NEED_VERIFY,且通过系统校验的申请单,将返回链接。 + * 2、建议将链接转为二维码展示,让商户法人用微信扫码打开,完成账户验证。 + * 示例值: https://pay.weixin.qq.com/public/apply4ec_sign/s?applymentId=2000002126198476&sign=b207b673049a32c858f3aabd7d27c7ec + *+ */ + @SerializedName(value = "legal_validation_url") + private String legalValidationUrl; + + /** + *
+ * 字段名:业务申请编号 + * 变量名:out_request_no + * 是否必填:是 + * 类型:string(124) + * 描述: + * 提交接口填写的业务申请编号。 + * 示例值:APPLYMENT_00000000001 + *+ */ + @SerializedName(value = "out_request_no") + private String outRequestNo; + + /** + *
+ * 字段名:微信支付申请单号 + * 变量名:applyment_id + * 是否必填:否 + * 类型:uint64 + * 描述: + * 微信支付分配的申请单号。 + * 示例值:2000002124775691 + *+ */ + @SerializedName(value = "applyment_id") + private String applymentId; + + @Data + @NoArgsConstructor + public static class AccountValidation implements Serializable{ + /** + *
+ * 字段名:付款户名 + * 变量名:account_name + * 是否必填:否 + * 类型:uint64 + * 描述: + * 需商户使用该户名的账户进行汇款。 + * 示例值: rDdICA3ZYXshYqeOSslSjSMf+MhhC4oaujiISFzq3AE+as7mAEDJly+DgRuVs74msmKUH8pl+3oA== + *+ */ + @SerializedName(value = "account_name") + private String accountName; + + /** + *
+ * 字段名:付款卡号 + * 变量名:account_no + * 是否必填:否 + * 类型:string(128) + * 描述: + * 结算账户为对私时会返回,商户需使用该付款卡号进行汇款。 + * 示例值:9nZYDEvBT4rDdICA3ZYXshYqeOSslSjSauAE+as7mAEDJly+DgRuVs74msmKUH8pl+3oA== + *+ */ + @SerializedName(value = "account_no") + private String accountNo; + + /** + *
+ * 字段名:汇款金额 + * 变量名:pay_amount + * 是否必填:否 + * 类型:string(32) + * 描述: + * 需要汇款的金额(单位:分)。 + * 示例值:124 + *+ */ + @SerializedName(value = "pay_amount") + private String payAmount; + + /** + *
+ * 字段名:收款卡号 + * 变量名:destination_account_number + * 是否必填:否 + * 类型:string(128) + * 描述: + * 收款账户的卡号 + * 示例值:7222223333322332 + *+ */ + @SerializedName(value = "destination_account_number") + private String destinationAccountNumber; + + /** + *
+ * 字段名:收款户名 + * 变量名:destination_account_name + * 是否必填:否 + * 类型:string(128) + * 描述: + * 收款账户名 + * 示例值:财付通支付科技有限公司 + *+ */ + @SerializedName(value = "destination_account_name") + private String destinationAccountName; + + /** + *
+ * 字段名:开户银行 + * 变量名:destination_account_bank + * 是否必填:否 + * 类型:string(128) + * 描述: + * 收款账户的开户银行名称。 + * 示例值:招商银行威盛大厦支行 + *+ */ + @SerializedName(value = "destination_account_bank") + private String destinationAccountBank; + + /** + *
+ * 字段名:省市信息 + * 变量名:city + * 是否必填:否 + * 类型:string(128) + * 描述: + * 收款账户的省市。 + * 示例值:深圳 + *+ */ + @SerializedName(value = "city") + private String city; + + /** + *
+ * 字段名:备注信息 + * 变量名:remark + * 是否必填:否 + * 类型:string(128) + * 描述: + * 商户汇款时,需要填写的备注信息。 + * 示例值:入驻账户验证 + *+ */ + @SerializedName(value = "remark") + private String remark; + + /** + *
+ * 字段名:汇款截止时间 + * 变量名:deadline + * 是否必填:否 + * 类型:string(20) + * 描述: + * 请在此时间前完成汇款。 + * 示例值:2018-12-1017:09:01 + *+ */ + @SerializedName(value = "deadline") + private String deadline; + + } + + @Data + @NoArgsConstructor + public static class AuditDetail implements Serializable{ + /** + *
+ * 字段名:参数名称 + * 变量名:param_name + * 是否必填:否 + * 类型:string(32) + * 描述: + * 提交申请单的资料项名称。 + * 示例值:id_card_copy + *+ */ + @SerializedName(value = "param_name") + private String paramName; + + /** + *
+ * 字段名:驳回原因 + * 变量名:reject_reason + * 是否必填:否 + * 类型:string(32) + * 描述: + * 提交资料项被驳回原因。 + * 示例值:身份证背面识别失败,请上传更清晰的身份证图片 + *+ */ + @SerializedName(value = "reject_reason") + private String rejectReason; + + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java index 097a0fa0c..2769e2201 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java @@ -130,6 +130,12 @@ public class WxPayConfig { * 私钥信息 */ private PrivateKey privateKey; + + /** + * 证书自动更新时间差(分钟),默认一分钟 + */ + private int certAutoUpdateTime = 60; + /** * p12证书文件内容的字节数组. */ @@ -245,8 +251,7 @@ public class WxPayConfig { AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)), - apiV3Key.getBytes(StandardCharsets.UTF_8)); - + apiV3Key.getBytes(StandardCharsets.UTF_8), this.getCertAutoUpdateTime()); CloseableHttpClient httpClient = WxPayV3HttpClientBuilder.create() .withMerchant(mchId, certSerialNo, merchantPrivateKey) diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java new file mode 100644 index 000000000..f1bdb2b3e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/EcommerceService.java @@ -0,0 +1,55 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsRequest; +import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsResult; +import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + *
+ * 电商收付通相关服务类. + * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3 + *+ * + * @author cloudX + * @date 2020/08/17 + */ +public interface EcommerceService { + /** + *
+ * 二级商户进件API + * 接口地址: https://api.mch.weixin.qq.com/v3/ecommerce/applyments/ + * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml + * + *+ * + * @param request 请求对象 + * @return . + */ + ApplymentsResult createApply(ApplymentsRequest request) throws WxPayException; + + /** + *
+ * 查询申请状态API
+ * 请求URL: https://api.mch.weixin.qq.com/v3/ecommerce/applyments/{applyment_id}
+ * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
+ *
+ *
+ * @param applymentId 申请单ID
+ * @return .
+ */
+ ApplymentsStatusResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException;
+
+ /**
+ *
+ * 查询申请状态API
+ * 请求URL: https://api.mch.weixin.qq.com/v3/ecommerce/applyments/out-request-no/{out_request_no}
+ * 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
+ *
+ *
+ * @param outRequestNo 业务申请编号
+ * @return .
+ */
+ ApplymentsStatusResult queryApplyStatusByOutRequestNo(String outRequestNo) throws WxPayException;
+
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
index da7652ef6..2324fba17 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java
@@ -126,6 +126,12 @@ public interface WxPayService {
*/
PayScoreService getPayScoreService();
+ /**
+ * 获取电商收付通服务类
+ * @return
+ */
+ EcommerceService getEcommerceService();
+
/**
* 设置企业付款服务类,允许开发者自定义实现类.
*
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
index efe9e70e0..3bd514a60 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java
@@ -62,6 +62,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
private ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this);
private RedpackService redpackService = new RedpackServiceImpl(this);
private PayScoreService payScoreService = new PayScoreServiceImpl(this);
+ private EcommerceService ecommerceService = new EcommerceServiceImpl(this);
/**
* The Config.
@@ -88,6 +89,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return this.redpackService;
}
+ @Override
+ public EcommerceService getEcommerceService() {
+ return ecommerceService;
+ }
+
@Override
public void setEntPayService(EntPayService entPayService) {
this.entPayService = entPayService;
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java
new file mode 100644
index 000000000..0c7e3821b
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/EcommerceServiceImpl.java
@@ -0,0 +1,52 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsRequest;
+import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsResult;
+import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult;
+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.util.RsaCryptoUtil;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.net.URI;
+
+public class EcommerceServiceImpl implements EcommerceService {
+
+ private static final Gson GSON = new GsonBuilder().create();
+ private WxPayService payService;
+
+ /**
+ *
+ * @param payService
+ */
+ public EcommerceServiceImpl(WxPayService payService) {
+ this.payService = payService;
+ }
+
+ @Override
+ public ApplymentsResult createApply(ApplymentsRequest request) throws WxPayException {
+ String url = String.format("%s/v3/ecommerce/applyments/", this.payService.getPayBaseUrl());
+ RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate());
+
+ String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
+ return GSON.fromJson(result, ApplymentsResult.class);
+ }
+
+ @Override
+ public ApplymentsStatusResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException {
+ String url = String.format("%s/v3/ecommerce/applyments/%s", this.payService.getPayBaseUrl(), applymentId);
+ String result = this.payService.getV3(URI.create(url));
+ return GSON.fromJson(result, ApplymentsStatusResult.class);
+ }
+
+ @Override
+ public ApplymentsStatusResult queryApplyStatusByOutRequestNo(String outRequestNo) throws WxPayException {
+ String url = String.format("%s/v3/ecommerce/applyments/out-request-no/%s", this.payService.getPayBaseUrl(), outRequestNo);
+ String result = this.payService.getV3(URI.create(url));
+ return GSON.fromJson(result, ApplymentsStatusResult.class);
+ }
+
+
+}
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java
index b6ab92316..d88c67e41 100644
--- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/v3/util/RsaCryptoUtil.java
@@ -29,10 +29,8 @@ public class RsaCryptoUtil {
public static void encryptFields(Object encryptObject, X509Certificate certificate) throws WxPayException {
try {
encryptField(encryptObject, certificate);
- } catch (IllegalAccessException | IllegalBlockSizeException e) {
+ } catch (Exception e) {
throw new WxPayException("敏感信息加密失败", e);
- } catch (Exception e2) {
- throw new WxPayException("敏感信息加密失败", e2);
}
}