diff --git a/src/main/java/weixin/popular/api/VehicleAPI.java b/src/main/java/weixin/popular/api/VehicleAPI.java new file mode 100644 index 00000000..c63a1e9a --- /dev/null +++ b/src/main/java/weixin/popular/api/VehicleAPI.java @@ -0,0 +1,178 @@ +package weixin.popular.api; + +import java.nio.charset.Charset; +import java.util.Map; + +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.entity.StringEntity; + +import weixin.popular.bean.vehicle.NavigateToOpenNoSense; +import weixin.popular.bean.vehicle.NavigateToOpenService; +import weixin.popular.bean.vehicle.PartnerpayNotification; +import weixin.popular.bean.vehicle.PartnerpayNotificationResult; +import weixin.popular.bean.vehicle.PartnerpayPayApply; +import weixin.popular.bean.vehicle.PartnerpayPayApplyResult; +import weixin.popular.bean.vehicle.PartnerpayQueryState; +import weixin.popular.bean.vehicle.PartnerpayQueryStateResult; +import weixin.popular.bean.vehicle.enums.TradeScene; +import weixin.popular.client.LocalHttpClient; +import weixin.popular.util.JsonUtil; +import weixin.popular.util.MapUtil; +import weixin.popular.util.SignatureUtil; +import weixin.popular.util.XMLConverUtil; + +/** + * 车主服务,只实现车主服务特有的接口,其他支付相关的接口和普通微信支付一样,调用PayMchAPI即可 + * + * 接口文档 + * https://pay.weixin.qq.com/wiki/doc/api/vehicle_v2_sl.php?chapter=2_3&index=1 + * + * @author around + * + */ +public class VehicleAPI extends BaseAPI { + + /** + * 入场通知 + * + * @param notification + * @param key + * @return + */ + public static PartnerpayNotificationResult partnerpayNotification(PartnerpayNotification notification, String key) { + Map map = MapUtil.objectToMap(notification); + if (notification.getScene_info() != null) { + map.put("scene_info", "{\"scene_info\":" + JsonUtil.toJSONString(notification.getScene_info()) + "}"); + } + String sign = SignatureUtil.generateSign(map, notification.getSign_type(), key); + notification.setSign(sign); + String xml = XMLConverUtil.convertToXML(notification); + HttpUriRequest httpUriRequest = RequestBuilder.post().setHeader(xmlHeader) + .setUri(MCH_URI + "/vehicle/partnerpay/notification") + .setEntity(new StringEntity(xml, Charset.forName("utf-8"))).build(); + return LocalHttpClient.executeXmlResult(httpUriRequest, PartnerpayNotificationResult.class, + notification.getSign_type(), key); + } + + /** + * 扣款请求 + * + * @param apply + * @param key + * @return + */ + public static PartnerpayPayApplyResult partnerpayPayApply(PartnerpayPayApply apply, String key) { + Map map = MapUtil.objectToMap(apply); + if (apply.getScene_info() != null) { + map.put("scene_info", "{\"scene_info\":" + JsonUtil.toJSONString(apply.getScene_info()) + "}"); + } + String sign = SignatureUtil.generateSign(map, apply.getSign_type(), key); + apply.setSign(sign); + String xml = XMLConverUtil.convertToXML(apply); + HttpUriRequest httpUriRequest = RequestBuilder.post().setHeader(xmlHeader) + .setUri(MCH_URI + "/vehicle/partnerpay/payapply") + .setEntity(new StringEntity(xml, Charset.forName("utf-8"))).build(); + return LocalHttpClient.executeXmlResult(httpUriRequest, PartnerpayPayApplyResult.class, apply.getSign_type(), + key); + } + + /** + * 查询用户状态 + * + * @param query + * @param key + * @return + */ + public static PartnerpayQueryStateResult partnerpayQueryState(PartnerpayQueryState query, String key) { + Map map = MapUtil.objectToMap(query); + String sign = SignatureUtil.generateSign(map, query.getSign_type(), key); + query.setSign(sign); + String xml = XMLConverUtil.convertToXML(query); + HttpUriRequest httpUriRequest = RequestBuilder.post().setHeader(xmlHeader) + .setUri(MCH_URI + "/vehicle/partnerpay/querystate") + .setEntity(new StringEntity(xml, Charset.forName("utf-8"))).build(); + return LocalHttpClient.executeXmlResult(httpUriRequest, PartnerpayQueryStateResult.class, query.getSign_type(), + key); + } + + /** + * 跳转到小程序/H5/APP,用户授权/开通车主服务 + * + * @param path + * @param tradeScene + * @param appid + * @param subAppid + * @param mchid + * @param subMchid + * @param openid + * @param subOpenid + * @param plateNumber + * @param materialInfo + * @param channelType + * @param key + * @return + */ + public static NavigateToOpenService navigateToOpenService(String path, TradeScene tradeScene, String appid, + String subAppid, String mchid, String subMchid, String openid, String subOpenid, String plateNumber, + String materialInfo, String channelType, String key) { + NavigateToOpenService nav = new NavigateToOpenService(); + nav.setPath(path); + NavigateToOpenService.ExtraData extraData = new NavigateToOpenService.ExtraData(); + extraData.setAppid(appid); + extraData.setSub_appid(subAppid); + extraData.setMch_id(mchid); + extraData.setSub_mch_id(subMchid); + extraData.setTrade_scene(tradeScene); + extraData.setOpenid(openid); + extraData.setSub_openid(subOpenid); + extraData.setChannel_type(channelType); + extraData.setMaterial_info(materialInfo); + extraData.setPlate_number(plateNumber); + extraData.setNonce_str(String.valueOf(System.currentTimeMillis())); + Map map = MapUtil.objectToMap(extraData); + extraData.setSign(SignatureUtil.generateSign(map, key)); + nav.setExtraData(extraData); + return nav; + } + + public static NavigateToOpenNoSense navigateToOpenNoSense(String appid, String subAppid, String mchid, + String subMchid, String openid, String plateNumber, String key) { + NavigateToOpenNoSense nav = new NavigateToOpenNoSense(); + NavigateToOpenNoSense.ExtraData extraData = new NavigateToOpenNoSense.ExtraData(); + extraData.setAppid(appid); + extraData.setSub_appid(subAppid); + extraData.setMch_id(mchid); + extraData.setSub_mch_id(subMchid); + extraData.setOpenid(openid); + extraData.setPlate_number(plateNumber); + extraData.setNonce_str(String.valueOf(System.currentTimeMillis())); + Map map = MapUtil.objectToMap(extraData); + extraData.setSign(SignatureUtil.generateSign(map, key)); + nav.setExtraData(extraData); + return nav; + } + + /** + * 支付中开通车主服务,需要申请开通权限 + * + * @param oldAttach + * @param plateNumber + * @param appid + * @return 下单时附加字段attach的字符串 + */ + public static String getAttachToOpenServiceOnPaying(String oldAttach, String plateNumber, String appid) { + return String.format("#*#{\"pn\":\"%s\",\"aid\":\"%s\"}#*#%s", plateNumber, appid, oldAttach); + } + + /** + * 在支付凭证中显示车主服务 + * + * @param oldAttach + * @return + */ + public static String getAttachToShowVehicleServiceInPayOrder(String oldAttach) { + return String.format("#*#{\"vm\":\"true\"}#*#%s", oldAttach); + } +} \ No newline at end of file diff --git a/src/main/java/weixin/popular/bean/vehicle/NavigateToAppForAuthExtraData.java b/src/main/java/weixin/popular/bean/vehicle/NavigateToAppForAuthExtraData.java new file mode 100644 index 00000000..8f4d8387 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/NavigateToAppForAuthExtraData.java @@ -0,0 +1,137 @@ +package weixin.popular.bean.vehicle; + +import java.util.Map; + +import weixin.popular.util.MapUtil; + +/** + * 跳转到小程序/H5/APP,用户授权/开通接口api + * + * @author around + * + */ +public class NavigateToAppForAuthExtraData { + + private String appid; + private String sub_appid; + private String mch_id; + private String sub_mch_id; + private String nonce_str; + private String sign_type = "HMAC-SHA256"; + private String sign; + private String openid; + private String sub_openid; + private String trade_scene; + private String plate_number; + private String material_info; + private String channel_type; + + public final String getAppid() { + return appid; + } + + public final void setAppid(String appid) { + this.appid = appid; + } + + public final String getSub_appid() { + return sub_appid; + } + + public final void setSub_appid(String sub_appid) { + this.sub_appid = sub_appid; + } + + public final String getMch_id() { + return mch_id; + } + + public final void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public final String getSub_mch_id() { + return sub_mch_id; + } + + public final void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public final String getNonce_str() { + return nonce_str; + } + + public final void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public final String getSign_type() { + return sign_type; + } + + public final void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public final String getSign() { + return sign; + } + + public final void setSign(String sign) { + this.sign = sign; + } + + public final String getTrade_scene() { + return trade_scene; + } + + public final void setTrade_scene(String trade_scene) { + this.trade_scene = trade_scene; + } + + public final String getOpenid() { + return openid; + } + + public final void setOpenid(String openid) { + this.openid = openid; + } + + public final String getSub_openid() { + return sub_openid; + } + + public final void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + public final String getPlate_number() { + return plate_number; + } + + public final void setPlate_number(String plate_number) { + this.plate_number = plate_number; + } + + public final String getMaterial_info() { + return material_info; + } + + public final void setMaterial_info(String material_info) { + this.material_info = material_info; + } + + public final String getChannel_type() { + return channel_type; + } + + public final void setChannel_type(String channel_type) { + this.channel_type = channel_type; + } + + public Map toMap(){ + return MapUtil.objectToMap(this); + } +} diff --git a/src/main/java/weixin/popular/bean/vehicle/NavigateToOpenService.java b/src/main/java/weixin/popular/bean/vehicle/NavigateToOpenService.java new file mode 100644 index 00000000..2453fa37 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/NavigateToOpenService.java @@ -0,0 +1,198 @@ +package weixin.popular.bean.vehicle; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Map; + +import weixin.popular.bean.vehicle.enums.TradeScene; +import weixin.popular.util.MapUtil; + +/** + * 跳转到小程序/H5/APP,用户授权/开通接口api + * + * @author around + * + */ +public class NavigateToOpenService { + + // 微信车主小程序appid,固定值。注意这个不是支付参数里的appid + private String appId = "wxbcad394b3d99dac9"; + private ExtraData extraData; + private String path; + + public final String getAppId() { + return appId; + } + + public final void setAppId(String appId) { + this.appId = appId; + } + + public ExtraData getExtraData() { + return extraData; + } + + public void setExtraData(ExtraData extraData) { + this.extraData = extraData; + } + + public final String getPath() { + return path; + } + + public final void setPath(String path) { + this.path = path; + } + + /** + * 获取H5跳转地址 + */ + public final String getH5Url() { + if (extraData == null) { + throw new IllegalArgumentException(); + } + StringBuilder url = new StringBuilder(); + if (path != null) { + url.append(path); + if (!path.endsWith("?")) { + url.append("?"); + } + } + try { + for (Map.Entry e : extraData.toMap().entrySet()) { + if (e.getValue() != null && e.getValue().length() > 0) { + url.append(e.getKey()).append("=").append(URLEncoder.encode(e.getValue(), "utf-8")).append("&"); + } + } + } catch (UnsupportedEncodingException e1) { + } + url = url.deleteCharAt(url.length() - 1).append("#wechat_redirect"); + return url.toString(); + } + + public static class ExtraData { + + private String appid; + private String sub_appid; + private String mch_id; + private String sub_mch_id; + private String nonce_str; + private String sign_type = "HMAC-SHA256"; + private String sign; + private String openid; + private String sub_openid; + private TradeScene trade_scene; + private String plate_number; + private String material_info; + private String channel_type; + + public final String getAppid() { + return appid; + } + + public final void setAppid(String appid) { + this.appid = appid; + } + + public final String getSub_appid() { + return sub_appid; + } + + public final void setSub_appid(String sub_appid) { + this.sub_appid = sub_appid; + } + + public final String getMch_id() { + return mch_id; + } + + public final void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public final String getSub_mch_id() { + return sub_mch_id; + } + + public final void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public final String getNonce_str() { + return nonce_str; + } + + public final void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public final String getSign_type() { + return sign_type; + } + + public final void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public final String getSign() { + return sign; + } + + public final void setSign(String sign) { + this.sign = sign; + } + + public final TradeScene getTrade_scene() { + return trade_scene; + } + + public final void setTrade_scene(TradeScene trade_scene) { + this.trade_scene = trade_scene; + } + + public final String getOpenid() { + return openid; + } + + public final void setOpenid(String openid) { + this.openid = openid; + } + + public final String getSub_openid() { + return sub_openid; + } + + public final void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + public final String getPlate_number() { + return plate_number; + } + + public final void setPlate_number(String plate_number) { + this.plate_number = plate_number; + } + + public final String getMaterial_info() { + return material_info; + } + + public final void setMaterial_info(String material_info) { + this.material_info = material_info; + } + + public final String getChannel_type() { + return channel_type; + } + + public final void setChannel_type(String channel_type) { + this.channel_type = channel_type; + } + + public Map toMap() { + return MapUtil.objectToMap(this); + } + } +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PartnerpayNotification.java b/src/main/java/weixin/popular/bean/vehicle/PartnerpayNotification.java new file mode 100644 index 00000000..856e7b6a --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PartnerpayNotification.java @@ -0,0 +1,56 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import weixin.popular.bean.vehicle.enums.TradeScene; + +/** + * 入场通知 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class PartnerpayNotification extends VehicleBaseReq { + + // 格式为json... + @XmlJavaTypeAdapter(value = SceneInfo.JsonXmlAdapter.class) + private SceneInfo scene_info; + + // 委托代扣的交易场景值,目前支持 : 1. PARKING:车场停车场景 ;2. PARKING SPACE 车位停车场景;该值催缴时会向微信用户进行展示 + private TradeScene trade_scene; + + /** + * @return the 场景信息 + */ + public final SceneInfo getScene_info() { + return scene_info; + } + + /** + * @param 场景信息 + * to set + */ + public final void setScene_info(SceneInfo scene_info) { + this.scene_info = scene_info; + } + + /** + * @return 场景 + */ + public final TradeScene getTrade_scene() { + return trade_scene; + } + + /** + * @param 场景 + * to set + */ + public final void setTrade_scene(TradeScene trade_scene) { + this.trade_scene = trade_scene; + } +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PartnerpayNotificationResult.java b/src/main/java/weixin/popular/bean/vehicle/PartnerpayNotificationResult.java new file mode 100644 index 00000000..84e50939 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PartnerpayNotificationResult.java @@ -0,0 +1,59 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import weixin.popular.bean.vehicle.enums.DeductMode; + +/** + * 入场通知结果 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class PartnerpayNotificationResult extends VehicleBaseResult { + + private String user_state; + private String openid; + private String sub_openid; + /** + * 3.0新增字段, 发起扣费的方式 PROACTIVE:表示用户主动发起的免密支付 AUTOPAY:表示用户无感的支付 + */ + private DeductMode deduct_mode; + + public final String getUser_state() { + return user_state; + } + + public final void setUser_state(String user_state) { + this.user_state = user_state; + } + + public final String getOpenid() { + return openid; + } + + public final void setOpenid(String openid) { + this.openid = openid; + } + + public final String getSub_openid() { + return sub_openid; + } + + public final void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + public DeductMode getDeduct_mode() { + return deduct_mode; + } + + public void setDeduct_mode(DeductMode deduct_mode) { + this.deduct_mode = deduct_mode; + } + +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PartnerpayPayApply.java b/src/main/java/weixin/popular/bean/vehicle/PartnerpayPayApply.java new file mode 100644 index 00000000..4c663a9a --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PartnerpayPayApply.java @@ -0,0 +1,145 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import weixin.popular.bean.vehicle.enums.TradeScene; + +/** + * 申请扣款 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class PartnerpayPayApply extends VehicleBaseReq { + + // 商品或支付单简要描述 + private String body; + // 商品名称明细列表 + private String detail; + private String attach; + private String out_trade_no; + private Integer total_fee; + private String fee_type; + private String spbill_create_ip; + private String goods_tag; + private String notify_url; + private String trade_type; + private String openid; + /** + * 1. PARKING:车场停车场景 2. PARKING SPACE;车位停车场景 3. GAS 加油场景 4. HIGHWAY 高速场景 + * 5.BRIDGE 路桥场景 + */ + private TradeScene trade_scene; + @XmlJavaTypeAdapter(value = SceneInfo.JsonXmlAdapter.class) + private SceneInfo scene_info; + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public Integer getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(Integer total_fee) { + this.total_fee = total_fee; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public String getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getGoods_tag() { + return goods_tag; + } + + public void setGoods_tag(String goods_tag) { + this.goods_tag = goods_tag; + } + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public TradeScene getTrade_scene() { + return trade_scene; + } + + public void setTrade_scene(TradeScene trade_scene) { + this.trade_scene = trade_scene; + } + + public SceneInfo getScene_info() { + return scene_info; + } + + public void setScene_info(SceneInfo scene_info) { + this.scene_info = scene_info; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PartnerpayPayApplyResult.java b/src/main/java/weixin/popular/bean/vehicle/PartnerpayPayApplyResult.java new file mode 100644 index 00000000..3560a821 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PartnerpayPayApplyResult.java @@ -0,0 +1,27 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * 申请扣款结果 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class PartnerpayPayApplyResult extends VehicleBaseResult { + + private String device_info; + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PartnerpayQueryState.java b/src/main/java/weixin/popular/bean/vehicle/PartnerpayQueryState.java new file mode 100644 index 00000000..10c6b6ff --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PartnerpayQueryState.java @@ -0,0 +1,79 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import weixin.popular.bean.vehicle.enums.JumpScene; +import weixin.popular.bean.vehicle.enums.TradeScene; + +/** + * 用户状态查询 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class PartnerpayQueryState extends VehicleBaseReq { + + private String openid; + + private String sub_openid; + + /** + * 委托代扣的交易场景值,目前支持 : 1. PARKING:车场停车场景 ; 2. PARKING SPACE 车位停车场景; 3. GAS 加油场景; + * 4. HIGHWAY 高速场景; 5. BRIDGE 路桥场景; 该值会向微信用户进行展示 + */ + private TradeScene trade_scene; + /** + * 商户跳转的业务场景,不传默认是小程序,也支持APP和公众号H5跳转 + * + * APP:通过APP跳转 + * + * H5:通过公众号H5跳转 + */ + private JumpScene jump_scene; + private String plate_number; + + public TradeScene getTrade_scene() { + return trade_scene; + } + + public void setTrade_scene(TradeScene trade_scene) { + this.trade_scene = trade_scene; + } + + public JumpScene getJump_scene() { + return jump_scene; + } + + public void setJump_scene(JumpScene jump_scene) { + this.jump_scene = jump_scene; + } + + public String getPlate_number() { + return plate_number; + } + + public void setPlate_number(String plate_number) { + this.plate_number = plate_number; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getSub_openid() { + return sub_openid; + } + + public void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PartnerpayQueryStateResult.java b/src/main/java/weixin/popular/bean/vehicle/PartnerpayQueryStateResult.java new file mode 100644 index 00000000..0064e129 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PartnerpayQueryStateResult.java @@ -0,0 +1,109 @@ +package weixin.popular.bean.vehicle; + +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +import weixin.popular.bean.DynamicField; +import weixin.popular.bean.vehicle.enums.DeductMode; +import weixin.popular.bean.vehicle.enums.UserState; + +/** + * 用户状态查询结果 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class PartnerpayQueryStateResult extends VehicleBaseResult implements DynamicField { + + private UserState user_state; + private String openid; + private String sub_openid; + + /** + * 跳转车主小程序的页面路径,如果该参数返回不为空,商户侧需调用‘用户授权/开通接口’引导用户进入车主小程序进行授权/开通的操作,‘用户授权/开通接口’请查看下面的详细说明; + * + * H5跳转同理,需跳转的场景有: -用户状态正常,但无车牌 -用户欠费 -用户未授权 -用户未开通/暂停车主服务 + */ + private String path; + // 车牌号列表。仅包括省份+车牌,不包括特殊字符。多个车牌时,以分好间隔。 + private String plate_number_list;// v2.0前 + private List plate_number_info;// v2.0以后返回这个 + + // 3.0新增 + private DeductMode deduct_mode; + + public UserState getUser_state() { + return user_state; + } + + public void setUser_state(UserState user_state) { + this.user_state = user_state; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getSub_openid() { + return sub_openid; + } + + public void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getPlate_number_list() { + return plate_number_list; + } + + public void setPlate_number_list(String plate_number_list) { + this.plate_number_list = plate_number_list; + } + + public List getPlate_number_info() { + return plate_number_info; + } + + public void setPlate_number_info(List plate_number_info) { + this.plate_number_info = plate_number_info; + } + + public DeductMode getDeduct_mode() { + return deduct_mode; + } + + public void setDeduct_mode(DeductMode deduct_mode) { + this.deduct_mode = deduct_mode; + } + + @Override + public void buildDynamicField(Map dataMap) { + String json = dataMap.get("plate_number_info"); + if (json != null) { + // {"plate_number_info":[{"plate_number":"粤B888888","channel_type":"ETC"}]} + JSONObject info = JSON.parseObject(json); + this.plate_number_info = JSON.parseArray(info.getString("plate_number_info"), PlateNumberInfo.class); + } + } +} diff --git a/src/main/java/weixin/popular/bean/vehicle/PlateNumberInfo.java b/src/main/java/weixin/popular/bean/vehicle/PlateNumberInfo.java new file mode 100644 index 00000000..23016ed3 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/PlateNumberInfo.java @@ -0,0 +1,46 @@ +package weixin.popular.bean.vehicle; + +/** + * 车牌信息 + * + * @author around + * + */ +public class PlateNumberInfo { + private String plate_number; + private String channel_type; + // 3.0新增 + private String common_use_flag; + + public PlateNumberInfo() { + } + + public PlateNumberInfo(String plate_number, String channel_type) { + this.plate_number = plate_number; + this.channel_type = channel_type; + } + + public String getPlate_number() { + return plate_number; + } + + public void setPlate_number(String plate_number) { + this.plate_number = plate_number; + } + + public String getChannel_type() { + return channel_type; + } + + public void setChannel_type(String channel_type) { + this.channel_type = channel_type; + } + + public String getCommon_use_flag() { + return common_use_flag; + } + + public void setCommon_use_flag(String common_use_flag) { + this.common_use_flag = common_use_flag; + } +} diff --git a/src/main/java/weixin/popular/bean/vehicle/SceneInfo.java b/src/main/java/weixin/popular/bean/vehicle/SceneInfo.java new file mode 100644 index 00000000..bddf5b71 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/SceneInfo.java @@ -0,0 +1,249 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import com.alibaba.fastjson.JSON; + +import weixin.popular.bean.vehicle.enums.DeductMode; +import weixin.popular.bean.vehicle.enums.SupportDeductMode; + +/** + * 场景信息,不同业务场景设置不同的值 + * + * @author around + * + */ +public class SceneInfo { + + private String start_time; + private String end_time; + private String plate_number; + private String notify_url; + private String car_type; + private String parking_name; + private String free_time; + private String openid; + private String sub_openid; + private String space_number; + private String charging_time; + private String gas_station; + private String gas_label_name; + private String gas_type; + private String gas_standard; + private String gas_amount; + private String gas_gun_no; + private String entrance_name; + private String exit_name; + private String carrying_capacity; + private String carrying_range; + private String channel_type; + private DeductMode deduct_mode; + private SupportDeductMode support_deduct_mode; + + public String getStart_time() { + return start_time; + } + + public void setStart_time(String start_time) { + this.start_time = start_time; + } + + public String getPlate_number() { + return plate_number; + } + + public void setPlate_number(String plate_number) { + this.plate_number = plate_number; + } + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getCar_type() { + return car_type; + } + + public void setCar_type(String car_type) { + this.car_type = car_type; + } + + public String getParking_name() { + return parking_name; + } + + public void setParking_name(String parking_name) { + this.parking_name = parking_name; + } + + public String getFree_time() { + return free_time; + } + + public void setFree_time(String free_time) { + this.free_time = free_time; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getSub_openid() { + return sub_openid; + } + + public void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + public String getSpace_number() { + return space_number; + } + + public void setSpace_number(String space_number) { + this.space_number = space_number; + } + + public String getEnd_time() { + return end_time; + } + + public void setEnd_time(String end_time) { + this.end_time = end_time; + } + + public String getCharging_time() { + return charging_time; + } + + public void setCharging_time(String charging_time) { + this.charging_time = charging_time; + } + + public String getGas_station() { + return gas_station; + } + + public void setGas_station(String gas_station) { + this.gas_station = gas_station; + } + + public String getGas_label_name() { + return gas_label_name; + } + + public void setGas_label_name(String gas_label_name) { + this.gas_label_name = gas_label_name; + } + + public String getGas_type() { + return gas_type; + } + + public void setGas_type(String gas_type) { + this.gas_type = gas_type; + } + + public String getGas_standard() { + return gas_standard; + } + + public void setGas_standard(String gas_standard) { + this.gas_standard = gas_standard; + } + + public String getGas_amount() { + return gas_amount; + } + + public void setGas_amount(String gas_amount) { + this.gas_amount = gas_amount; + } + + public String getGas_gun_no() { + return gas_gun_no; + } + + public void setGas_gun_no(String gas_gun_no) { + this.gas_gun_no = gas_gun_no; + } + + public String getEntrance_name() { + return entrance_name; + } + + public void setEntrance_name(String entrance_name) { + this.entrance_name = entrance_name; + } + + public String getExit_name() { + return exit_name; + } + + public void setExit_name(String exit_name) { + this.exit_name = exit_name; + } + + public String getCarrying_capacity() { + return carrying_capacity; + } + + public void setCarrying_capacity(String carrying_capacity) { + this.carrying_capacity = carrying_capacity; + } + + public String getCarrying_range() { + return carrying_range; + } + + public void setCarrying_range(String carrying_range) { + this.carrying_range = carrying_range; + } + + public String getChannel_type() { + return channel_type; + } + + public void setChannel_type(String channel_type) { + this.channel_type = channel_type; + } + + public DeductMode getDeduct_mode() { + return deduct_mode; + } + + public void setDeduct_mode(DeductMode deduct_mode) { + this.deduct_mode = deduct_mode; + } + + public SupportDeductMode getSupport_deduct_mode() { + return support_deduct_mode; + } + + public void setSupport_deduct_mode(SupportDeductMode support_deduct_mode) { + this.support_deduct_mode = support_deduct_mode; + } + + static class JsonXmlAdapter extends XmlAdapter { + + @Override + public String marshal(SceneInfo v) throws Exception { + return "{\"scene_info\":" + JSON.toJSONString(v) + "}"; + } + + @Override + public SceneInfo unmarshal(String v) throws Exception { + return JSON.parseObject(v, PartnerpayNotification.class).getScene_info(); + } + + } + +} diff --git a/src/main/java/weixin/popular/bean/vehicle/StateChangeNotification.java b/src/main/java/weixin/popular/bean/vehicle/StateChangeNotification.java new file mode 100644 index 00000000..2282d455 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/StateChangeNotification.java @@ -0,0 +1,195 @@ +package weixin.popular.bean.vehicle; + +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +import weixin.popular.bean.DynamicField; +import weixin.popular.bean.vehicle.enums.DeductMode; + +/** + * 车牌状态变更通知 + * + * @author around + * + */ +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class StateChangeNotification implements DynamicField { + + private String mch_id; + private String sub_mch_id; + private String appid; + private String sub_appid; + private String plate_number; + /** + * 当前通知车牌的状态变化类型: NORMAL-变为可用状态 BLOCKED-变为不可用状态 注意此状态是车牌状态,而非用户状态 + */ + private String vehicle_event_type; + /** + * 当前车牌状态,所对应的事件类型为BLOCKED时返回: + * + * OVERDUE: 车牌对应用户欠费。商户引导用户还款,请跳转到车主服务 + * + * REMOVE:用户移除车牌导致车牌不可用。请跳转到授权/开通接口。 + * + * PAUSE: 用户关闭或已暂停车主服务导致车牌不可用。请跳转到授权/开通接口 + */ + private String vehicle_event_des; + private String nonce_str; + private String sign_type; + private String sign; + private String vehicle_event_createtime; + + private String openid; + private String sub_openid; + private String plate_number_list;// v2.0前 + // v2.0以后返回这个 + private List plate_number_info; + // 3.0 + private DeductMode deduct_mode; + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getSub_mch_id() { + return sub_mch_id; + } + + public void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getSub_appid() { + return sub_appid; + } + + public void setSub_appid(String sub_appid) { + this.sub_appid = sub_appid; + } + + public String getPlate_number() { + return plate_number; + } + + public void setPlate_number(String plate_number) { + this.plate_number = plate_number; + } + + public String getVehicle_event_type() { + return vehicle_event_type; + } + + public void setVehicle_event_type(String vehicle_event_type) { + this.vehicle_event_type = vehicle_event_type; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign_type() { + return sign_type; + } + + public void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getVehicle_event_createtime() { + return vehicle_event_createtime; + } + + public void setVehicle_event_createtime(String vehicle_event_createtime) { + this.vehicle_event_createtime = vehicle_event_createtime; + } + + public String getVehicle_event_des() { + return vehicle_event_des; + } + + public void setVehicle_event_des(String vehicle_event_des) { + this.vehicle_event_des = vehicle_event_des; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getSub_openid() { + return sub_openid; + } + + public void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + public String getPlate_number_list() { + return plate_number_list; + } + + public void setPlate_number_list(String plate_number_list) { + this.plate_number_list = plate_number_list; + } + + public List getPlate_number_info() { + return plate_number_info; + } + + public void setPlate_number_info(List plate_number_info) { + this.plate_number_info = plate_number_info; + } + + public DeductMode getDeduct_mode() { + return deduct_mode; + } + + public void setDeduct_mode(DeductMode deduct_mode) { + this.deduct_mode = deduct_mode; + } + + @Override + public void buildDynamicField(Map dataMap) { + String json = dataMap.get("plate_number_info"); + if (json != null) { + // {"plate_number_info":[{"plate_number":"粤B888888","channel_type":"ETC"}]} + JSONObject info = JSON.parseObject(json); + this.plate_number_info = JSON.parseArray(info.getString("plate_number_info"), PlateNumberInfo.class); + } + } +} diff --git a/src/main/java/weixin/popular/bean/vehicle/VehicleBaseReq.java b/src/main/java/weixin/popular/bean/vehicle/VehicleBaseReq.java new file mode 100644 index 00000000..a5fb8a2a --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/VehicleBaseReq.java @@ -0,0 +1,25 @@ +package weixin.popular.bean.vehicle; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; + +import weixin.popular.bean.paymch.MchBase; + +/** + * 请求参数 + */ +@XmlAccessorType(XmlAccessType.FIELD) +public abstract class VehicleBaseReq extends MchBase { + + // default 2.0 + private String version = "2.0"; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + +} diff --git a/src/main/java/weixin/popular/bean/vehicle/VehicleBaseResult.java b/src/main/java/weixin/popular/bean/vehicle/VehicleBaseResult.java new file mode 100644 index 00000000..b9578d73 --- /dev/null +++ b/src/main/java/weixin/popular/bean/vehicle/VehicleBaseResult.java @@ -0,0 +1,110 @@ +package weixin.popular.bean.vehicle; + +public abstract class VehicleBaseResult { + + private String return_code; + + private String return_msg; + + private String appid; + private String sub_appid; + private String mch_id; + private String sub_mch_id; + private String nonce_str; + private String sign; + private String result_code; + private String err_code; + private String err_code_des; + + public boolean isSuccess() { + return "SUCCESS".equals(this.return_code); + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getSub_appid() { + return sub_appid; + } + + public void setSub_appid(String sub_appid) { + this.sub_appid = sub_appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getSub_mch_id() { + return sub_mch_id; + } + + public void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } +}