Commit 03d5462b authored by 刘帅's avatar 刘帅

1.接入银联支付

parent 86b9122f
......@@ -180,3 +180,11 @@ sms:
sdkAppId: appid
#地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
territory: ap-guangzhou
pay:
appid: 10037e6f72b586db0172b6ea24ec0000
appkey: 6f7a00170935445fbe25e67a5ce1be48
url: https://test-api-open.chinaums.com/v6/poslink/transaction/pay
merchantCode: 123456789111115
terminalCode: gxrb0001
deviceType: 11
payMode: CODE_SCAN
......@@ -183,3 +183,11 @@ sms:
sdkAppId: appid
#地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
territory: ap-guangzhou
pay:
appid: 10037e6f72b586db0172b6ea24ec0000
appkey: 6f7a00170935445fbe25e67a5ce1be48
url: https://test-api-open.chinaums.com/v6/poslink/transaction/pay
merchantCode: 123456789111115
terminalCode: gxrb0001
deviceType: 11
payMode: CODE_SCAN
......@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Arrays;
import java.util.stream.Collectors;
import com.maintain.business.domain.bo.ErpSettlementMaintainPayBo;
import com.maintain.business.domain.bo.ErpSettlementMaintainRepairFormBo;
import com.maintain.business.domain.vo.ErpSettlementMaintainRepairFormVo;
import com.maintain.business.service.IErpRepairFormService;
......@@ -137,4 +138,16 @@ public class ErpSettlementMaintainController extends BaseController {
public R<Void> receipt(@Validated(EditGroup.class) @RequestBody ErpSettlementMaintainBo bo) {
return toAjax(iErpSettlementMaintainService.receiptByBo(bo));
}
/**
* 结算维修单回执
*
* @param bo
*/
@Log(title = "结算维修单支付", businessType = BusinessType.UPDATE)
@PutMapping("/pay")
public R<Void> pay(@Validated(EditGroup.class) @RequestBody ErpSettlementMaintainPayBo bo) {
return toAjax(iErpSettlementMaintainService.pay(bo));
}
}
......@@ -71,9 +71,13 @@ public class ErpSettlementMaintain extends BaseEntity {
*/
private Date settlementTime;
/**
* 支付方式(1支付宝 2微信
* 支付方式(1扫码支付 2手动支付
*/
private Integer paymentMethod;
/**
* 支付单号
*/
private String paymentNumber;
/**
* 付款账号
*/
......@@ -111,7 +115,7 @@ public class ErpSettlementMaintain extends BaseEntity {
*/
private String collectionAccount;
/**
* 收款流水号
* 交易流水号
*/
private String collectionSerialNumber;
/**
......
......@@ -90,7 +90,6 @@ public class ErpSettlementMaintainBo extends BaseEntity {
/**
* 支付方式(1支付宝 2微信)
*/
@NotNull(message = "支付方式(1支付宝 2微信)不能为空", groups = { AddGroup.class, EditGroup.class })
private Integer paymentMethod;
/**
......@@ -106,7 +105,6 @@ public class ErpSettlementMaintainBo extends BaseEntity {
/**
* 付款凭证
*/
@NotBlank(message = "付款凭证不能为空", groups = { AddGroup.class, EditGroup.class })
private String paymentVoucher;
/**
......
package com.maintain.business.domain.bo;
import com.maintain.common.core.domain.BaseEntity;
import com.maintain.common.core.validate.AddGroup;
import com.maintain.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 结算维修单业务对象 erp_settlement_maintain
*
* @author liushuai
* @date 2025-04-03
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ErpSettlementMaintainPayBo extends BaseEntity {
/**
* 结算单ID
*/
@NotNull(message = "结算单ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long id;
/**
* 付款码
*/
@NotBlank(message = "付款码不能为空", groups = { AddGroup.class, EditGroup.class })
private String paymentAccount;
}
package com.maintain.business.service;
import com.maintain.business.domain.ErpSettlementMaintain;
import com.maintain.business.domain.vo.ErpSettlementMaintainVo;
import com.maintain.business.domain.bo.ErpSettlementMaintainBo;
import com.maintain.common.core.page.TableDataInfo;
import com.maintain.business.domain.bo.ErpSettlementMaintainPayBo;
import com.maintain.business.domain.vo.ErpSettlementMaintainVo;
import com.maintain.common.core.domain.PageQuery;
import com.maintain.common.core.page.TableDataInfo;
import java.util.Collection;
import java.util.List;
......@@ -53,4 +53,11 @@ public interface IErpSettlementMaintainService {
* @return
*/
Boolean receiptByBo(ErpSettlementMaintainBo bo);
/**
* 结算维修单支付
* @param bo
* @return
*/
Boolean pay(ErpSettlementMaintainPayBo bo);
}
package com.maintain.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.maintain.business.domain.ErpRepairForm;
import com.maintain.business.domain.ErpSettlementMaintain;
import com.maintain.business.domain.ErpSettlementMaintainRepairForm;
import com.maintain.business.domain.bo.ErpSettlementMaintainRepairFormBo;
import com.maintain.business.domain.bo.ErpSettlementMaintainBo;
import com.maintain.business.domain.bo.ErpSettlementMaintainPayBo;
import com.maintain.business.domain.vo.ErpClientVo;
import com.maintain.business.domain.vo.ErpSettlementMaintainVo;
import com.maintain.business.mapper.ErpClientMapper;
import com.maintain.business.mapper.ErpRepairFormMapper;
import com.maintain.business.mapper.ErpSettlementMaintainMapper;
import com.maintain.business.mapper.ErpSettlementMaintainRepairFormMapper;
import com.maintain.business.service.IErpSettlementMaintainService;
import com.maintain.common.core.domain.PageQuery;
import com.maintain.common.core.page.TableDataInfo;
import com.maintain.common.enums.RepairFormSettlementState;
import com.maintain.common.enums.SettlementState;
import com.maintain.common.exception.ServiceException;
import com.maintain.common.helper.LoginHelper;
import com.maintain.common.pay.PayResponse;
import com.maintain.common.pay.YinLianPayApi;
import com.maintain.common.utils.StringUtils;
import com.maintain.common.core.page.TableDataInfo;
import com.maintain.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.maintain.common.utils.redis.RedisUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.maintain.business.domain.bo.ErpSettlementMaintainBo;
import com.maintain.business.domain.vo.ErpSettlementMaintainVo;
import com.maintain.business.domain.ErpSettlementMaintain;
import com.maintain.business.mapper.ErpSettlementMaintainMapper;
import com.maintain.business.service.IErpSettlementMaintainService;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
......@@ -49,6 +53,9 @@ public class ErpSettlementMaintainServiceImpl implements IErpSettlementMaintainS
private final ErpSettlementMaintainRepairFormMapper settlementMaintainRepairFormMapper;
private final ErpRepairFormMapper repairFormMapper;
private final ErpClientMapper clientMapper;
private final YinLianPayApi yinLianPayApi;
@Value("${pay.merchantCode}")
private String merchantCode;
/**
* 查询结算维修单
......@@ -204,4 +211,39 @@ public class ErpSettlementMaintainServiceImpl implements IErpSettlementMaintainS
}
return flag;
}
/**
* 结算维修单支付
*
* @param bo
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public Boolean pay(ErpSettlementMaintainPayBo bo) {
ErpSettlementMaintain maintain = baseMapper.selectById(bo.getId());
if (ObjectUtil.isEmpty(maintain)) {
throw new ServiceException("当前支付订单不存在,请刷新后重试!");
}
if (maintain.getState().equals(SettlementState.TWO.getCode())) {
throw new ServiceException("当前结算单已支付,不能重复支付!");
}
// 生成一个时间戳单号
String orderNo = String.valueOf(System.currentTimeMillis());
int money = maintain.getPracticalMoney().movePointRight(2).intValue();
PayResponse response = yinLianPayApi.pay(orderNo, money, bo.getPaymentAccount());
if (!response.getErrCode().equals("00")) {
throw new ServiceException("结算单支付失败:"+ response.getErrInfo());
}
maintain.setCollectionAccount(merchantCode);
maintain.setCollectionSerialNumber(response.getOrderId());
maintain.setCollectionTime(new Date());
maintain.setState(SettlementState.TWO.getCode());
maintain.setPaymentMethod(1);
maintain.setPaymentAccount(bo.getPaymentAccount());
maintain.setPaymentNumber(orderNo);
baseMapper.updateById(maintain);
return true;
}
}
......@@ -10,8 +10,8 @@ import lombok.Getter;
@Getter
public enum SettlementState {
ONE(1, "待确认"),
TWO(2, "已确认");
ONE(1, "待支付"),
TWO(2, "已支付");
private final Integer code;
private final String info;
......
package com.maintain.common.pay;
/**
* PayResponse
*
* @author Liu Shuai
* @date 2025/10/28 14:30
*/
public class PayResponse {
/**
* errCode : 00
* errInfo : 10000成功响应码
* transactionTime : 140747
* transactionDate : 1028
* settlementDate : 1028
* transactionDateWithYear : 20251028
* settlementDateWithYear : 20251028
* retrievalRefNum : 01479200019N
* transactionAmount : 1
* actualTransactionAmount : 1
* amount : 1
* orderId : 20251028140747440012928716
* thirdPartyDiscountInstrution : 微信钱包支付0.01元
* thirdPartyDiscountInstruction : 微信钱包支付0.01元
* thirdPartyName : 微信钱包
* userId : oUpF8uMv_IaPg4f03FtZSQ7TiAiM
* thirdPartyBuyerId : oUpF8uMv_IaPg4f03FtZSQ7TiAiM
* thirdPartyOrderId : 4200002861202510289915715464
* thirdPartyPayInformation : 现金:1
* cardAttr : 91
* mchntName : 测试商户
* chnlType : WXPay
* promotionAmt : 0
* systemTraceNum : 002841
*/
private String errCode;
private String errInfo;
private String transactionTime;
private String transactionDate;
private String settlementDate;
private String transactionDateWithYear;
private String settlementDateWithYear;
private String retrievalRefNum;
private int transactionAmount;
private int actualTransactionAmount;
private int amount;
private String orderId;
private String thirdPartyDiscountInstrution;
private String thirdPartyDiscountInstruction;
private String thirdPartyName;
private String userId;
private String thirdPartyBuyerId;
private String thirdPartyOrderId;
private String thirdPartyPayInformation;
private String cardAttr;
private String mchntName;
private String chnlType;
private String promotionAmt;
private String systemTraceNum;
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrInfo() {
return errInfo;
}
public void setErrInfo(String errInfo) {
this.errInfo = errInfo;
}
public String getTransactionTime() {
return transactionTime;
}
public void setTransactionTime(String transactionTime) {
this.transactionTime = transactionTime;
}
public String getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(String transactionDate) {
this.transactionDate = transactionDate;
}
public String getSettlementDate() {
return settlementDate;
}
public void setSettlementDate(String settlementDate) {
this.settlementDate = settlementDate;
}
public String getTransactionDateWithYear() {
return transactionDateWithYear;
}
public void setTransactionDateWithYear(String transactionDateWithYear) {
this.transactionDateWithYear = transactionDateWithYear;
}
public String getSettlementDateWithYear() {
return settlementDateWithYear;
}
public void setSettlementDateWithYear(String settlementDateWithYear) {
this.settlementDateWithYear = settlementDateWithYear;
}
public String getRetrievalRefNum() {
return retrievalRefNum;
}
public void setRetrievalRefNum(String retrievalRefNum) {
this.retrievalRefNum = retrievalRefNum;
}
public int getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(int transactionAmount) {
this.transactionAmount = transactionAmount;
}
public int getActualTransactionAmount() {
return actualTransactionAmount;
}
public void setActualTransactionAmount(int actualTransactionAmount) {
this.actualTransactionAmount = actualTransactionAmount;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getThirdPartyDiscountInstrution() {
return thirdPartyDiscountInstrution;
}
public void setThirdPartyDiscountInstrution(String thirdPartyDiscountInstrution) {
this.thirdPartyDiscountInstrution = thirdPartyDiscountInstrution;
}
public String getThirdPartyDiscountInstruction() {
return thirdPartyDiscountInstruction;
}
public void setThirdPartyDiscountInstruction(String thirdPartyDiscountInstruction) {
this.thirdPartyDiscountInstruction = thirdPartyDiscountInstruction;
}
public String getThirdPartyName() {
return thirdPartyName;
}
public void setThirdPartyName(String thirdPartyName) {
this.thirdPartyName = thirdPartyName;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getThirdPartyBuyerId() {
return thirdPartyBuyerId;
}
public void setThirdPartyBuyerId(String thirdPartyBuyerId) {
this.thirdPartyBuyerId = thirdPartyBuyerId;
}
public String getThirdPartyOrderId() {
return thirdPartyOrderId;
}
public void setThirdPartyOrderId(String thirdPartyOrderId) {
this.thirdPartyOrderId = thirdPartyOrderId;
}
public String getThirdPartyPayInformation() {
return thirdPartyPayInformation;
}
public void setThirdPartyPayInformation(String thirdPartyPayInformation) {
this.thirdPartyPayInformation = thirdPartyPayInformation;
}
public String getCardAttr() {
return cardAttr;
}
public void setCardAttr(String cardAttr) {
this.cardAttr = cardAttr;
}
public String getMchntName() {
return mchntName;
}
public void setMchntName(String mchntName) {
this.mchntName = mchntName;
}
public String getChnlType() {
return chnlType;
}
public void setChnlType(String chnlType) {
this.chnlType = chnlType;
}
public String getPromotionAmt() {
return promotionAmt;
}
public void setPromotionAmt(String promotionAmt) {
this.promotionAmt = promotionAmt;
}
public String getSystemTraceNum() {
return systemTraceNum;
}
public void setSystemTraceNum(String systemTraceNum) {
this.systemTraceNum = systemTraceNum;
}
}
......@@ -51,3 +51,13 @@ export function receiptSettlementMaintain(data) {
data: data
})
}
// 结算维修单回执
export function paySettlementMaintain(data) {
return request({
url: '/business/settlementMaintain/pay',
method: 'put',
data: data,
timeout: 30000
})
}
......@@ -58,6 +58,8 @@
<el-table-column label="证件号" align="center" prop="clientCertificateNumber" width="100px" show-overflow-tooltip/>
<el-table-column label="工时费优惠" align="center" prop="manHourDiscountMoney" />
<el-table-column label="原料费优惠" align="center" prop="materialDiscountMoney" />
<el-table-column label="应收金额" align="center" prop="receivableMoney" />
<el-table-column label="结算金额" align="center" prop="practicalMoney" />
<el-table-column label="结算时间" align="center" prop="settlementTime" width="120">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.settlementTime, '{y}-{m}-{d}') }}</span>
......@@ -281,8 +283,8 @@
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="收款流水号" prop="collectionSerialNumber">
<el-input v-model="form.collectionSerialNumber" placeholder="请输入收款流水号" />
<el-form-item label="交易流水号" prop="collectionSerialNumber">
<el-input v-model="form.collectionSerialNumber" placeholder="请输入交易流水号" />
</el-form-item>
</el-col>
</el-row>
......@@ -303,11 +305,25 @@
</el-form>
</el-scrollbar>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="qrOpen">扫码支付</el-button>
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 扫码支付对话框 -->
<el-dialog :title="title" :visible.sync="open2" width="500px" append-to-body>
<el-form ref="payForm" :model="payForm" :rules="payRules" label-width="80px">
<el-form-item label="支付码" prop="paymentAccount">
<el-input ref="payCodeInput" v-model="payForm.paymentAccount" placeholder="使用设备扫描条形码" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="payButtonLoading" type="primary" @click="paySubmitForm">确认支付</el-button>
<el-button :loading="payButtonLoading" @click="open2 = false"> </el-button>
</div>
</el-dialog>
<!-- 详情对话框 -->
<el-dialog :title="title" :visible.sync="open1" width="80%" append-to-body>
<el-scrollbar style="height: 75vh;">
......@@ -392,7 +408,7 @@
import {
delSettlementMaintain,
getSettlementMaintain,
listSettlementMaintain,
listSettlementMaintain, paySettlementMaintain,
receiptSettlementMaintain
} from '@/api/business/settlementMaintain'
......@@ -403,6 +419,7 @@ export default {
return {
// 按钮loading
buttonLoading: false,
payButtonLoading: false,
// 遮罩层
loading: true,
// 选中数组
......@@ -422,6 +439,7 @@ export default {
// 是否显示弹出层
open: false,
open1: false,
open2: false,
// 查询参数
queryParams: {
pageNum: 1,
......@@ -433,6 +451,10 @@ export default {
},
// 表单参数
form: {},
payForm: {
id: undefined,
paymentAccount: undefined,
},
// 表单校验
rules: {
collectionTime: [
......@@ -444,8 +466,13 @@ export default {
collectionSerialNumber: [
{ required: true, message: "收款流水号不能为空", trigger: "blur" }
],
collectionVoucher: [
{ required: true, message: "收款回执不能为空", trigger: "change" }
// collectionVoucher: [
// { required: true, message: "收款回执不能为空", trigger: "change" }
// ],
},
payRules: {
paymentAccount: [
{ required: true, message: "支付码不能为空", trigger: "blur" }
],
}
};
......@@ -526,6 +553,38 @@ export default {
this.title = "结算维修单详情";
});
},
/** 扫码支付按钮操作 */
qrOpen() {
this.payForm = {
id: this.form.id,
paymentAccount: undefined,
}
this.open2 = true;
this.title = "扫码支付";
this.$nextTick(() => {
// 确保输入框存在并获取焦点
if (this.$refs.payCodeInput && this.$refs.payCodeInput.focus) {
this.$refs.payCodeInput.focus()
}
})
},
/** 确认支付按钮操作 */
paySubmitForm() {
this.$refs["payForm"].validate(valid => {
if (valid) {
this.payButtonLoading = true;
paySettlementMaintain(this.payForm).then(response => {
this.$modal.msgSuccess("支付成功");
this.open2 = false;
getSettlementMaintain(this.form.id).then(response => {
this.form = response.data;
});
}).finally(() => {
this.payButtonLoading = false;
});
}
});
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
......
......@@ -119,13 +119,13 @@
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="支付方式" prop="paymentMethod">
<el-select v-model="form.paymentMethod" placeholder="请选择支付方式" style="width: 100%">
<el-option v-for="item in dict.type.settlement_payment_method" :key="item.value" :value="parseInt(item.value)" :label="item.label" />
</el-select>
</el-form-item>
</el-col>
<!-- <el-col :span="6">-->
<!-- <el-form-item label="支付方式" prop="paymentMethod">-->
<!-- <el-select v-model="form.paymentMethod" placeholder="请选择支付方式" style="width: 100%">-->
<!-- <el-option v-for="item in dict.type.settlement_payment_method" :key="item.value" :value="parseInt(item.value)" :label="item.label" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6">
<el-form-item label="结算时间" prop="settlementTime">
<el-date-picker clearable
......@@ -280,9 +280,9 @@ export default {
paymentAccountName: [
{ required: true, message: "账号名称不能为空", trigger: "blur" }
],
paymentVoucher: [
{ required: true, message: "付款凭证不能为空", trigger: "blur" }
],
// paymentVoucher: [
// { required: true, message: "付款凭证不能为空", trigger: "blur" }
// ],
},
};
},
......@@ -378,7 +378,7 @@ export default {
this.buttonLoading = false;
}).finally(() => {
this.buttonLoading = false;
this.$tab.closeOpenPage({path: '/settlement/settlementMaintain?clientType=1'})
this.$tab.closeOpenPage({path: '/settlement/settlementMaintain?clientType=2'})
});
}
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment