!23 新增支付分相关接口

Merge pull request !23 from smart/develop
This commit is contained in:
egan
2023-10-09 13:14:01 +00:00
committed by Gitee
13 changed files with 735 additions and 4 deletions

View File

@@ -0,0 +1,142 @@
package com.egzosn.pay.demo.controller;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.wx.v3.api.WxPayScoreService;
import com.egzosn.pay.wx.v3.api.WxPayConfigStorage;
import com.egzosn.pay.wx.v3.api.WxPayService;
import com.egzosn.pay.wx.v3.bean.payscore.*;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
@RestController
@RequestMapping("/wxV3CreditScore")
public class WxV3PayScoreController {
private WxPayService service3 = null;
private WxPayScoreService wxPayScoreService = null;
private static final String APPID = "wxc7b993ff15a9f26c";
private static final String SERVICE_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private static final String MCH_ID = "1602947765"; // 商户号
private static final String V3_API_KEY = "9bd8f0e7af4841299d782406b7774f57";
// @PostConstruct
public void init() {
WxPayConfigStorage paymentStandardConfig = new WxPayConfigStorage();
paymentStandardConfig.setAppid(APPID);
paymentStandardConfig.setServiceId(SERVICE_ID);
paymentStandardConfig.setMchId(MCH_ID);
paymentStandardConfig.setV3ApiKey(V3_API_KEY);
paymentStandardConfig.setNotifyUrl("http://sailinmu.iok.la/wxV3combine/payBack.json");
paymentStandardConfig.setInputCharset("UTF-8");
paymentStandardConfig.setSignType("MD5");
paymentStandardConfig.setCertStoreType(CertStoreType.PATH);
paymentStandardConfig.setApiClientKeyP12("apiclient_cert.p12");
HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
httpConfigStorage.setStorePassword(MCH_ID);
httpConfigStorage.setKeystore("apiclient_cert.p12");
service3 = new WxPayService(paymentStandardConfig,httpConfigStorage);
wxPayScoreService = new WxPayScoreService(paymentStandardConfig,httpConfigStorage);
}
@PostMapping("/refund")
public RefundResult refund() {
RefundOrder refundOrder = new RefundOrder();
refundOrder.setRefundNo("R2023082416493947872");
refundOrder.setTradeNo("4200001930202308240314610507");
//订单号
refundOrder.setOutTradeNo("P2023082416243247872");
//退款金额
refundOrder.setRefundAmount(new BigDecimal("0.01"));
//退款备注
refundOrder.setDescription("退款测试");
refundOrder.setCurType(DefaultCurType.CNY);
//总金额
refundOrder.setTotalAmount(new BigDecimal("0.01"));
refundOrder.addAttr("funds_account","AVAILABLE");
return service3.refund(refundOrder);
}
@GetMapping("/queryOrder")
public Map<String, Object> queryOrder(AssistOrder order) {
return wxPayScoreService.query(order);
}
@GetMapping("/queryRefundOrder")
public Map<String, Object> queryRefundOrder(RefundOrder refundOrder) {
return service3.refundquery(refundOrder);
}
@PostMapping("/create")
public Map<String,Object> create() {
CreateOrder createOrder = new CreateOrder();
createOrder.setOutTradeNo("P2023091301010100000");
createOrder.setStartTime("OnAccept");
//paymentRequest.setStartTime(DateUtils.formatDate(new Date(),DateUtils.YYYYMMDDHHMMSS));
createOrder.setServiceIntroduction("测试");
createOrder.setRiskFundAmount(new BigDecimal("1.11"));
createOrder.setRiskFundName("ESTIMATE_ORDER_COST");
createOrder.setOpenId("oZu615JDX_H9Ni4KXmiXzuCKiBqQ");
return wxPayScoreService.create(createOrder);
}
@PostMapping("/cancel")
public Map<String,Object> cancel() {
//撤销智慧零售
CancelOrder cancelOrder = new CancelOrder();
cancelOrder.setOutTradeNo("商户订单号");
cancelOrder.setReason("测试");
return wxPayScoreService.cancel(cancelOrder.getOutTradeNo(),cancelOrder.getReason());
}
@PostMapping("/modify")
public Map<String,Object> modify() {
//修改订单金额
ModifyOrder modifyOrder = new ModifyOrder();
modifyOrder.setOutTradeNo("P2023091301010100000");
PostPayment postPayment = new PostPayment();
postPayment.setAmount(BigDecimal.ONE);
postPayment.setName("ESTIMATE_ORDER_COST");
modifyOrder.setPostPayments(Arrays.asList(postPayment));
modifyOrder.setTotalAmount(BigDecimal.ONE);
modifyOrder.setReason("test");
return wxPayScoreService.modify(modifyOrder);
}
@PostMapping("/complete")
public Map<String,Object> complete() {
//修改订单金额
CompleteOrder completeOrder = new CompleteOrder();
completeOrder.setOutTradeNo("P2023091301010100000");
PostPayment postPayment = new PostPayment();
postPayment.setAmount(BigDecimal.ONE);
postPayment.setName("ESTIMATE_ORDER_COST");
completeOrder.setPostPayments(Arrays.asList(postPayment));
completeOrder.setTotalAmount(BigDecimal.ONE);
return wxPayScoreService.complete(completeOrder);
}
@PostMapping("/sync")
public Map<String,Object> sync() {
//修改订单金额
SyncOrder syncOrder = new SyncOrder();
syncOrder.setOutTradeNo("商户订单号");
syncOrder.setPaidTime(new Date());
return wxPayScoreService.sync(syncOrder.getOutTradeNo(),syncOrder.getPaidTime());
}
}

View File

@@ -78,8 +78,10 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
* 是否为服务商模式, 默认为false
*/
private boolean partner = false;
/**
* 微信支付分服务服务ID
*/
private String serviceId;
@Deprecated
@Override
@@ -263,4 +265,12 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
public void setPartner(boolean partner) {
this.partner = partner;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
}

View File

@@ -0,0 +1,179 @@
package com.egzosn.pay.wx.v3.api;
import com.alibaba.fastjson.JSON;
import com.egzosn.pay.common.bean.AssistOrder;
import com.egzosn.pay.common.bean.Order;
import com.egzosn.pay.common.bean.OrderParaStructure;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.http.UriVariables;
import com.egzosn.pay.common.util.DateUtils;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.wx.v3.bean.WxPayScoreTransactionType;
import com.egzosn.pay.wx.v3.bean.payscore.*;
import com.egzosn.pay.wx.v3.utils.WxConst;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* 微信支付分API服务
*
* @author neon
* date 2023/9/12
*/
public class WxPayScoreService extends WxPayService{
public WxPayScoreService(WxPayConfigStorage payConfigStorage) {
super(payConfigStorage);
}
public WxPayScoreService(WxPayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
super(payConfigStorage, configStorage);
}
private Map<String, Object> getPublicParameters() {
Map<String, Object> parameters = new TreeMap<>();
parameters.put("appid", payConfigStorage.getAppId());
parameters.put("mch_id", payConfigStorage.getPid());
parameters.put("service_id", payConfigStorage.getServiceId());
return parameters;
}
/**
* 初始化通知URL必须为直接可访问的URL不允许携带查询串要求必须为https地址。
*
* @param parameters 订单参数
* @param order 订单信息
*/
public void initNotifyUrl(Map<String, Object> parameters, Order order) {
OrderParaStructure.loadParameters(parameters, WxConst.NOTIFY_URL, payConfigStorage.getNotifyUrl());
OrderParaStructure.loadParameters(parameters, WxConst.NOTIFY_URL, order);
}
/**
* 商户预授权API
*/
public Map<String, Object> permissions(String authorizationCode) {
Map<String, Object> parameters = getPublicParameters();
OrderParaStructure.loadParameters(parameters,WxConst.AUTHORIZATION_CODE,authorizationCode);
OrderParaStructure.loadParameters(parameters, WxConst.NOTIFY_URL, payConfigStorage.getNotifyUrl());
return getAssistService().doExecute(parameters, WxPayScoreTransactionType.PERMISSIONS);
}
public Map<String, Object> queryPermissionsByAuthorizationCode(String authorizationCode) {
Map<String, Object> parameters = getPublicParameters();
OrderParaStructure.loadParameters(parameters,WxConst.AUTHORIZATION_CODE,authorizationCode);
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.QUERY_PERMISSIONS_AUTHORIZATION_CODE,authorizationCode);
}
public Map<String, Object> terminatePermissionsByAuthorizationCode(String authorizationCode,String reason) {
Map<String, Object> parameters = getPublicParameters();
OrderParaStructure.loadParameters(parameters,WxConst.AUTHORIZATION_CODE,authorizationCode);
OrderParaStructure.loadParameters(parameters,"reason",reason);
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.UNBIND_PERMISSIONS_AUTHORIZATION_CODE,authorizationCode);
}
public Map<String, Object> queryPermissionsByOpenId(String openId) {
Map<String, Object> parameters = getPublicParameters();
OrderParaStructure.loadParameters(parameters,"open_id",openId);
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.QUERY_PERMISSIONS_OPENID,openId);
}
public Map<String, Object> terminatePermissionsByOpenId(String openId,String reason) {
Map<String, Object> parameters = getPublicParameters();
OrderParaStructure.loadParameters(parameters,"open_id",openId);
OrderParaStructure.loadParameters(parameters,"reason",reason);
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.UNBIND_PERMISSIONS_OPENID,openId);
}
/**
* 微信创建支付分订单
*/
public Map<String,Object> create(CreateOrder createOrder) {
Map<String, Object> parameters = getPublicParameters();
OrderParaStructure.loadParameters(parameters,"out_order_no", createOrder.getOutTradeNo());
OrderParaStructure.loadParameters(parameters,"service_introduction", createOrder.getServiceIntroduction());
RiskFund riskFund = new RiskFund();
riskFund.setName(createOrder.getRiskFundName());
riskFund.setAmount(createOrder.getRiskFundAmount());
parameters.put("risk_fund",riskFund);
String attach = createOrder.getAttach();
if (StringUtils.isNotBlank(attach)) {
String attachEncode = URLEncoder.encode(attach);
OrderParaStructure.loadParameters(parameters,"attach",attachEncode.length() <= 256 ? attachEncode : attachEncode.substring(0, 255));
}
TimeRange timeRange = new TimeRange();
timeRange.setStartTime(createOrder.getStartTime());
timeRange.setEndTime(createOrder.getEndTime());
parameters.put("time_range", timeRange);
initNotifyUrl(parameters, createOrder);
OrderParaStructure.loadParameters(parameters,"openid", createOrder.getOpenId());
if (null != createOrder.getNeedUserConfirm()) {
OrderParaStructure.loadParameters(parameters,"need_user_confirm", createOrder.getNeedUserConfirm().toString());
}
return getAssistService().doExecute(parameters, WxPayScoreTransactionType.CREATE);
}
/**
* 支付分订单撤销
*/
@Override
public Map<String,Object> cancel(String orderNo, String reason) {
Map<String, Object> parameters = getPublicParameters();
reason = reason.length() <= 50 ? reason : reason.substring(0, 50);
parameters.put("reason", reason);
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.CANCEL, orderNo);
}
public Map<String,Object> modify(ModifyOrder modifyOrder) {
Map<String, Object> parameters = getPublicParameters();
parameters.put("post_payments", modifyOrder.getPostPayments());
parameters.put("total_amount", modifyOrder.getTotalAmount());
OrderParaStructure.loadParameters(parameters,"reason", modifyOrder.getReason());
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.MODIFY, modifyOrder.getOutTradeNo());
}
public Map<String,Object> complete(CompleteOrder completeOrder){
Map<String, Object> parameters = getPublicParameters();
parameters.put("post_payments", completeOrder.getPostPayments());
parameters.put("total_amount", completeOrder.getTotalAmount());
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.COMPLETE, completeOrder.getOutTradeNo());
}
public Map<String,Object> sync(String outOrderNo, Date payTime){
Map<String, Object> parameters = getPublicParameters();
parameters.put("type", "Order_Paid");
Map<String,Object> detail = new HashMap<>();
detail.put("paid_time", DateUtils.formatDate(payTime,DateUtils.YYYYMMDDHHMMSS));
parameters.put("detail", detail);
String params = JSON.toJSONString(parameters);
return getAssistService().doExecute(params, WxPayScoreTransactionType.SYNC,outOrderNo);
}
@Override
public Map<String, Object> query(AssistOrder assistOrder){
String outTradeNo = assistOrder.getOutTradeNo();
Map<String, Object> publicParameters = getPublicParameters();
if (StringUtils.isNotBlank(outTradeNo)) {
OrderParaStructure.loadParameters(publicParameters,"out_order_no",outTradeNo);
}
String parameters = UriVariables.getMapToParameters(publicParameters);
return getAssistService().doExecute(parameters, WxPayScoreTransactionType.QUERY);
}
}

View File

@@ -0,0 +1,54 @@
package com.egzosn.pay.wx.v3.bean;
import com.egzosn.pay.common.bean.MethodType;
import com.egzosn.pay.common.bean.TransactionType;
public enum WxPayScoreTransactionType implements TransactionType {
PERMISSIONS("/v3/payscore/permissions", MethodType.POST),
QUERY_PERMISSIONS_AUTHORIZATION_CODE("/v3/payscore/permissions/authorization-code/{authorization_code}", MethodType.POST),
UNBIND_PERMISSIONS_AUTHORIZATION_CODE("/v3/payscore/permissions/authorization-code/{authorization_code}/terminate", MethodType.POST),
QUERY_PERMISSIONS_OPENID("/v3/payscore/permissions/openid/{openid}", MethodType.POST),
UNBIND_PERMISSIONS_OPENID("/v3/payscore/permissions/openid/{openid}/terminate", MethodType.POST),
CREATE("/v3/payscore/serviceorder", MethodType.POST),
CANCEL("/v3/payscore/serviceorder/{out_order_no}/cancel", MethodType.POST),
COMPLETE("/v3/payscore/serviceorder/{out_order_no}/complete", MethodType.POST),
SYNC("/v3/payscore/serviceorder/{out_order_no}/sync", MethodType.POST),
MODIFY("/v3/payscore/serviceorder/{out_order_no}/modify", MethodType.POST),
QUERY("/v3/payscore/serviceorder", MethodType.GET),
;
WxPayScoreTransactionType(String type, MethodType method) {
this.type = type;
this.method = method;
}
private String type;
private MethodType method;
@Override
public String getType() {
return type;
}
@Override
public String getMethod() {
return this.method.name();
}
}

View File

@@ -0,0 +1,16 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.egzosn.pay.common.bean.AssistOrder;
public class CancelOrder extends AssistOrder {
private String reason;
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}

View File

@@ -0,0 +1,39 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.alibaba.fastjson.annotation.JSONField;
import java.math.BigDecimal;
import java.util.List;
public class CompleteOrder extends CreateOrder {
private BigDecimal totalAmount;
@JSONField(name="post_payments")
private List<PostPayment> postPayments;
private Boolean profitSharing = false;
public BigDecimal getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}
public List<PostPayment> getPostPayments() {
return postPayments;
}
public void setPostPayments(List<PostPayment> postPayments) {
this.postPayments = postPayments;
}
public Boolean getProfitSharing() {
return profitSharing;
}
public void setProfitSharing(Boolean profitSharing) {
this.profitSharing = profitSharing;
}
}

View File

@@ -0,0 +1,95 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.egzosn.pay.common.bean.AssistOrder;
import java.math.BigDecimal;
public class CreateOrder extends AssistOrder {
private String openId;
private String serviceIntroduction;
/**
* 服务开始时间
* 支持三种格式yyyyMMddHHmmss、yyyyMMdd和OnAccept
*/
private String startTime;
private String endTime;
private String riskFundName;
private BigDecimal riskFundAmount;
private String attach;
private Boolean needUserConfirm;
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getServiceIntroduction() {
return serviceIntroduction;
}
public void setServiceIntroduction(String serviceIntroduction) {
this.serviceIntroduction = serviceIntroduction;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public String getRiskFundName() {
return riskFundName;
}
public void setRiskFundName(String riskFundName) {
this.riskFundName = riskFundName;
}
public BigDecimal getRiskFundAmount() {
return riskFundAmount;
}
public void setRiskFundAmount(BigDecimal riskFundAmount) {
this.riskFundAmount = riskFundAmount;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public Boolean getNeedUserConfirm() {
return needUserConfirm;
}
public void setNeedUserConfirm(Boolean needUserConfirm) {
this.needUserConfirm = needUserConfirm;
}
}

View File

@@ -0,0 +1,42 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.alibaba.fastjson.annotation.JSONField;
import com.egzosn.pay.common.bean.AssistOrder;
import java.math.BigDecimal;
import java.util.List;
public class ModifyOrder extends AssistOrder {
private BigDecimal totalAmount;
@JSONField(name="post_payments")
private List<PostPayment> postPayments;
private String reason;
public BigDecimal getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}
public List<PostPayment> getPostPayments() {
return postPayments;
}
public void setPostPayments(List<PostPayment> postPayments) {
this.postPayments = postPayments;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}

View File

@@ -0,0 +1,59 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import java.io.Serializable;
import java.math.BigDecimal;
public class PostPayment implements Serializable {
/**
* 付费项目名称
*/
private String name;
/**
* 金额
*/
private BigDecimal amount;
/**
* 说明
*/
private String description;
/**
* 数量
*/
private Integer count;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}

View File

@@ -0,0 +1,48 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.egzosn.pay.common.util.Util;
import java.io.Serializable;
import java.math.BigDecimal;
public class RiskFund implements Serializable {
/**
* 风险金名称
*/
private String name;
/**
* 风险金额
*/
private BigDecimal amount;
/**
* 风险说明
*/
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAmount() {
return Util.conversionCentAmount(amount);
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@@ -0,0 +1,18 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.egzosn.pay.common.bean.AssistOrder;
import java.util.Date;
public class SyncOrder extends AssistOrder {
private Date paidTime;
public Date getPaidTime() {
return paidTime;
}
public void setPaidTime(Date paidTime) {
this.paidTime = paidTime;
}
}

View File

@@ -0,0 +1,30 @@
package com.egzosn.pay.wx.v3.bean.payscore;
import com.alibaba.fastjson.annotation.JSONField;
import java.io.Serializable;
public class TimeRange implements Serializable {
@JSONField(name = "start_time")
private String startTime;
@JSONField(name = "end_time")
private String endTime;
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}

View File

@@ -84,6 +84,5 @@ public final class WxConst {
public static final String LIMIT = "limit";
public static final String DETAIL_STATUS = "detail_status";
public static final String WECHATPAY_SERIAL = "Wechatpay-Serial";
public static final String AUTHORIZATION_CODE = "authorization_code";
}