ManagementIGOTravel/guns-admin/pom.xml
@@ -226,6 +226,11 @@ <artifactId>jsoup</artifactId> <version>1.13.1</version> </dependency> <dependency> <groupId>io.cellulant</groupId> <artifactId>CheckoutEncryption</artifactId> <version>0.0.1</version> </dependency> </dependencies> ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/config/web/ShiroConfig.java
@@ -160,6 +160,7 @@ * */ Map<String, String> hashMap = new LinkedHashMap<>(); hashMap.put("/base/**", "anon"); hashMap.put("/static/**", "anon"); hashMap.put("/gunsApi/**", "anon"); hashMap.put("/login", "anon"); ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TPubWithdrawalController.java
@@ -1,5 +1,7 @@ package com.stylefeng.guns.modular.system.controller.general; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.stylefeng.guns.core.base.controller.BaseController; import com.stylefeng.guns.core.common.constant.factory.PageFactory; @@ -8,19 +10,28 @@ import com.stylefeng.guns.core.util.ExcelExportUtil; import com.stylefeng.guns.core.util.SinataUtil; import com.stylefeng.guns.core.util.ToolUtil; import com.stylefeng.guns.modular.system.util.Tingg.model.*; import com.stylefeng.guns.modular.system.model.TDriver; import com.stylefeng.guns.modular.system.model.TPubWithdrawal; import com.stylefeng.guns.modular.system.model.TSystemNotice; import com.stylefeng.guns.modular.system.model.TUser; import com.stylefeng.guns.modular.system.service.ITDriverService; import com.stylefeng.guns.modular.system.service.ITPubWithdrawalService; import com.stylefeng.guns.modular.system.service.ITSystemNoticeService; import com.stylefeng.guns.modular.system.util.HttpRequestUtil; import com.stylefeng.guns.modular.system.util.PushURL; import com.stylefeng.guns.modular.system.service.ITUserService; import com.stylefeng.guns.modular.system.util.ResultUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import com.stylefeng.guns.modular.system.util.Tingg.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; /** @@ -39,6 +50,22 @@ @Autowired private ITSystemNoticeService tSystemNoticeService; @Autowired private TinggPayoutUtil tinggPayoutUtil; @Autowired private ITUserService userService; @Autowired private ITDriverService driverService; @Value("${callbackPath}") private String callbackPath; /** * 跳转到提现列表首页 @@ -117,23 +144,53 @@ public Object immediately(@RequestParam Integer id,@RequestParam Integer state,@RequestParam String remark) { TPubWithdrawal tPubWithdrawal = tPubWithdrawalService.selectById(id); if (SinataUtil.isNotEmpty(tPubWithdrawal)){ // tPubWithdrawal.setState(state); //调用接口修改状态 tPubWithdrawal.setRemark(remark); tPubWithdrawal.setHandleTime(new Date()); Integer stateObj = 1; if (2 == state){ //同意提现 stateObj = 1; }else if (3 == state){ //拒绝提现 stateObj = 2; String serviceCode = ""; String phone = ""; if(tPubWithdrawal.getUserType() == 1){ TUser tUser = userService.selectById(tPubWithdrawal.getUserId()); serviceCode = tUser.getPhoneOperator(); phone = tUser.getPhone(); }else{ TDriver tDriver = driverService.selectById(tPubWithdrawal.getUserId()); serviceCode = tDriver.getPhoneOperator(); phone = tDriver.getPhone(); } if(2 == state){ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String payerTransactionID = sdf.format(new Date()) + tPubWithdrawal.getId(); PayoutResponse payoutResponse = tinggPayoutUtil.sendPayout(serviceCode, "+" + phone, payerTransactionID, tPubWithdrawal.getMoney().doubleValue(), callbackPath + "/tPubWithdrawal/base/withdrawalCallback", "用户提现"); AuthStatus authStatus = payoutResponse.getAuthStatus(); Results results = payoutResponse.getResults().get(0); String statusCode = results.getStatusCode(); if(!"131".equals(authStatus.getAuthStatusCode())){ return ResultUtil.error(authStatus.getAuthStatusDescription()); } if(!"139".equals(statusCode)){ return ResultUtil.error(results.getStatusDescription()); } tPubWithdrawal.setSerialNo(results.getBeepTransactionID()); }else{//回退金额 tPubWithdrawal.setHandleTime(new Date()); tPubWithdrawal.setState(state); if(tPubWithdrawal.getUserType() == 1){ TUser tUser = userService.selectById(tPubWithdrawal.getUserId()); tUser.setBalance(tUser.getBalance().add(tPubWithdrawal.getMoney())); userService.updateById(tUser); }else{ TDriver tDriver = driverService.selectById(tPubWithdrawal.getUserId()); tDriver.setBalance(tDriver.getBalance().add(tPubWithdrawal.getMoney())); if(tPubWithdrawal.getType() == 1){//活动提现 tDriver.setLaveActivityMoney(new BigDecimal(tDriver.getLaveActivityMoney()).add(tPubWithdrawal.getMoney()).setScale(2, RoundingMode.HALF_EVEN).doubleValue()); }else{//业务提现 tDriver.setLaveBusinessMoney(new BigDecimal(tDriver.getLaveBusinessMoney()).add(tPubWithdrawal.getMoney()).setScale(2, RoundingMode.HALF_EVEN).doubleValue()); } driverService.updateById(tDriver); } } tPubWithdrawalService.updateById(tPubWithdrawal); Map<String,String> map = new HashMap<>(); map.put("id", String.valueOf(tPubWithdrawal.getId())); map.put("state", String.valueOf(stateObj)); String result = HttpRequestUtil.postRequest(PushURL.withdraw_auth_url, map); System.out.println("提现审核接口 :【recordId="+tPubWithdrawal.getId().toString()+"】,调用接口:"+result); //增加系统消息 TSystemNotice notice = new TSystemNotice(); @@ -148,6 +205,40 @@ return SUCCESS_TIP; } @ResponseBody @PostMapping("/base/withdrawalCallback") public PayoutCallbackResponse tinggPayoutCallback(@RequestBody PayoutCallbackRequest request){ System.err.println("转账回调>>>>" + JSON.toJSONString(request)); PayoutCallbackResponse payoutCallbackResponse = new PayoutCallbackResponse(); AuthStatus authStatus = new AuthStatus(); authStatus.setAuthStatusCode(131); authStatus.setAuthStatusDescription("Authentication was successful"); payoutCallbackResponse.setAuthStatus(authStatus); Results results = new Results(); PayoutPacket packet = request.getPayload().getPacket(); String statusCode = packet.getStatusCode(); String beepTransactionID = packet.getBeepTransactionID(); String payerTransactionID = packet.getPayerTransactionID(); String id = payerTransactionID.substring(17); TPubWithdrawal tPubWithdrawal = tPubWithdrawalService.selectById(id); tPubWithdrawal.setState(2); tPubWithdrawal.setHandleTime(new Date()); tPubWithdrawal.setSerialNo(beepTransactionID); tPubWithdrawalService.updateById(tPubWithdrawal); results.setBeepTransactionID(beepTransactionID); results.setPayerTransactionID(payerTransactionID); results.setStatusCode("188"); results.setStatusDescription("Response was received"); payoutCallbackResponse.setResults(results); return payoutCallbackResponse; } /** * 修改提现列表 */ ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TDriver.java
@@ -34,6 +34,11 @@ */ private String jobNumber; /** * 手机号运营商 */ @TableField("phoneOperator") private String phoneOperator; /** * 手机号 */ private String phone; @@ -421,6 +426,14 @@ this.phone = phone; } public String getPhoneOperator() { return phoneOperator; } public void setPhoneOperator(String phoneOperator) { this.phoneOperator = phoneOperator; } public String getPassword() { return password; } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TPubWithdrawal.java
@@ -1,5 +1,6 @@ package com.stylefeng.guns.modular.system.model; import com.baomidou.mybatisplus.annotations.TableField; import com.baomidou.mybatisplus.enums.IdType; import java.math.BigDecimal; import java.util.Date; @@ -63,6 +64,11 @@ */ private Integer userType; /** * 提现类型(1=活动收入提现,2=业务收入提现) */ @TableField("type") private Integer type; /** * 申请时间 */ private Date insertTime; @@ -74,6 +80,12 @@ * 提现方式 1=银行卡 2=线下 */ private Integer withdrawalType; /** * 银行提交转账申请后的交易序列号,用于查询交易状态 * @return */ @TableField("serialNo") private String serialNo; public Integer getId() { @@ -180,6 +192,22 @@ this.withdrawalType = withdrawalType; } public String getSerialNo() { return serialNo; } public void setSerialNo(String serialNo) { this.serialNo = serialNo; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } @Override protected Serializable pkVal() { return this.id; ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/model/TUser.java
@@ -45,6 +45,11 @@ */ private String phone; /** * 手机号运营商 */ @TableField("phoneOperator") private String phoneOperator; /** * 昵称 */ private String nickName; @@ -195,6 +200,14 @@ this.phone = phone; } public String getPhoneOperator() { return phoneOperator; } public void setPhoneOperator(String phoneOperator) { this.phoneOperator = phoneOperator; } public String getNickName() { return nickName; } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/TinggPayUtil.java
New file @@ -0,0 +1,107 @@ package com.stylefeng.guns.modular.system.util.Tingg; import com.alibaba.fastjson.JSON; import com.stylefeng.guns.modular.system.util.ResultUtil; import com.stylefeng.guns.modular.system.util.Tingg.model.CallbackRequest; import com.stylefeng.guns.modular.system.util.Tingg.model.CheckoutRequest; import io.cellulant.model.Payload; import io.cellulant.service.CheckoutEncryption; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Date; /** * Tingg支付工具类 */ public class TinggPayUtil { private static String accessKey = "8rc1gTV9n91Tc1Sy9oVWry99fgrgrVV8concf9onWooWSg9TVW8nSgo98g88"; private static String ivKey = "ABp0pqpHMteEJM2N"; private static String secretKey = "rf8Vo1n9yTSW98cg"; /** * 获取支付数据 * @param checkoutRequest * @return */ public static ResultUtil checkoutRequest(CheckoutRequest checkoutRequest){ try { CheckoutEncryption checkoutEncrption = new CheckoutEncryption(ivKey, secretKey); Payload payload = getPayload(checkoutRequest); String param = checkoutEncrption.encrypt(payload); System.out.println("Encrpted payload=" + param); String url = "https://checkout.tingg.africa/express/checkout?encrypted_payload=" + param + "&access_key=" + accessKey; return ResultUtil.success(url); }catch (Exception e){ e.printStackTrace(); return ResultUtil.runErr(); } } public static Payload getPayload(CheckoutRequest checkoutRequest) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String countryCode="GHA";//收取付款的国家的3位ISO代码 String currencyCode = "GHS";//3位ISO代码的货币,商家正在开发票。 String serviceCode="I-GO_TECHNOLOGIES_LI";//服务代码 String dueDate = sdf.format(new Date(System.currentTimeMillis() + 1800000));//到期时间 String languageCode="EN"; String paymentOptionCode = "";//支付选项码 Payload payload = new Payload(checkoutRequest.getMerchantTransactionId(), checkoutRequest.getCustomerFirstName(), checkoutRequest.getCustomerLastName(), checkoutRequest.getMsisdn(), checkoutRequest.getCustomerEmail(), checkoutRequest.getRequestAmount(), currencyCode, checkoutRequest.getAccountNumber(), serviceCode, dueDate, checkoutRequest.getRequestDescription(), countryCode, languageCode, paymentOptionCode, checkoutRequest.getSuccessRedirectUrl(), checkoutRequest.getFailRedirectUrl(), checkoutRequest.getPendingRedirectUrl(), checkoutRequest.getCallbackUrl()); return payload; } public static CallbackRequest getRequestParam(HttpServletRequest request) throws IOException { // 读取参数 InputStream inputStream; StringBuilder sb = new StringBuilder(); inputStream = request.getInputStream(); String s; BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); while ((s = in.readLine()) != null) { sb.append(s); } in.close(); inputStream.close(); String json = sb.toString(); System.err.println("结果-----》" + json); CallbackRequest callbackRequest = JSON.parseObject(json, CallbackRequest.class); return callbackRequest; } public static void main(String[] ages){ CheckoutRequest checkoutRequest = new CheckoutRequest(); checkoutRequest.setMsisdn(Long.valueOf("2030376339310")); checkoutRequest.setCustomerEmail("393733352@qq.com"); checkoutRequest.setAccountNumber("2030376339310"); checkoutRequest.setCustomerFirstName("ZHONGSHI"); checkoutRequest.setCustomerLastName("HUANG"); checkoutRequest.setRequestAmount(1.00D); checkoutRequest.setMerchantTransactionId("00024"); checkoutRequest.setRequestDescription("payment test"); checkoutRequest.setCallbackUrl("https://10pz685243.zicp.fun/base/IGO/wxCancelUserBalance"); checkoutRequest.setPendingRedirectUrl("https://www.baidu.com"); checkoutRequest.setSuccessRedirectUrl("https://www.baidu.com"); checkoutRequest.setFailRedirectUrl("https://www.baidu.com"); ResultUtil resultUtil = TinggPayUtil.checkoutRequest(checkoutRequest); System.err.println(JSON.toJSONString(resultUtil)); } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/TinggPayoutUtil.java
New file @@ -0,0 +1,73 @@ package com.stylefeng.guns.modular.system.util.Tingg; import com.alibaba.fastjson.JSON; import com.stylefeng.guns.modular.system.util.Tingg.model.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * 转账 * @author zhibing.pu * @date 2023/3/17 9:48 */ @Component public class TinggPayoutUtil { @Autowired private RestTemplate restTemplate; /** * 转账接口 * @param phone 电话号码,带国家代码+233 * @param payerTransactionID 支付单号 * @param amount 支付金额 * @param callbackUrl 回调地址 * @param narration 备注 * @return */ public PayoutResponse sendPayout(String serviceCode, String phone, String payerTransactionID, Double amount, String callbackUrl, String narration) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Credentials credentials = new Credentials("igo_api_user", "mXo%kJM.p;_i)SSZ&^b?6XSH)D+OCPh8"); List<Packet> packets = new ArrayList<>(); Packet packet = new Packet(); packet.setServiceCode(serviceCode);//手机网络运营商 GH-MTN-B2C、GH-TIGO-B2C、GH-VODAFONE-B2C、GH-AIRTEL-B2C packet.setMSISDN(phone); packet.setAccountNumber(phone); packet.setPayerTransactionID(payerTransactionID); packet.setAmount(amount); packet.setNarration(narration); packet.setDatePaymentReceived(sdf.format(new Date())); packet.setExtraData(new ExtraData(callbackUrl)); packet.setCurrencyCode("GHS"); packets.add(packet); Payload payload = new Payload(credentials, packets); Payout payout = new Payout("GH", "BEEP.postPayment", payload); String string = JSON.toJSONString(payout); string = string.replace("mSISDN", "MSISDN"); System.err.println(string); HttpHeaders headers = new HttpHeaders(); MediaType type = MediaType.parseMediaType("text/plain"); headers.setContentType(type); headers.add("Accept", MediaType.APPLICATION_JSON.toString()); HttpEntity<String> formEntity = new HttpEntity<>(string, headers); String url = "https://apps.cellulant.co.ke:9801/globalApi/v2/JSON/"; String s = restTemplate.postForObject(url, formEntity, String.class); PayoutResponse payoutResponse = JSON.parseObject(s, PayoutResponse.class); System.err.println(s); return payoutResponse; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/AuthStatus.java
New file @@ -0,0 +1,35 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * @author zhibing.pu * @date 2023/3/20 16:52 */ public class AuthStatus { /** * 认证状态码 * 131 客户端认证成功 * 132 客户端认证失败 * 174 具有匹配的适当描述的通用故障状态代码 */ private Integer authStatusCode; /** * 账号认证说明 */ private String authStatusDescription; public Integer getAuthStatusCode() { return authStatusCode; } public void setAuthStatusCode(Integer authStatusCode) { this.authStatusCode = authStatusCode; } public String getAuthStatusDescription() { return authStatusDescription; } public void setAuthStatusDescription(String authStatusDescription) { this.authStatusDescription = authStatusDescription; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/CallbackRequest.java
New file @@ -0,0 +1,255 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; /** * 支付回调 */ public class CallbackRequest { /** * Cellulant末端的唯一标识符。 */ private Long checkout_request_id; /** * 商家单号 */ private String merchant_transaction_id; /** * 支付金额 */ private Double request_amount; /** * 由商家以发票货币提出的原始请求金额 */ private Double original_request_amount; /** * 为客户支付的请求转换的货币。 */ private String request_currency_code; /** * 商家在ISO代码中提出要求的货币代码。 */ private String original_request_currency_code; /** * 支付账户。 */ private String account_number; /** * 所支付的ISO货币代码 */ private String currency_code; /** * 客户为请求支付的金额。 */ private Double amount_paid; /** * 为发起的请求添加到服务中的费用。 */ private Double service_charge_amount; /** * 提出请求的日期。 */ private Date request_date; /** * 唯一的服务代码,用于标识引发支付请求的服务。 */ private String service_code; /** * 指示服务是否成功或付费的总体请求代码。。 * 177-部分付费请求 * 178-表明请求已全额支付 * 179-表示请求已部分支付但已过期。 * 129-请求已过期,未付款。 * 180.商户拒绝请求 * 183-商户接受请求,我们可以结算资金 * 188-商户收到请求。 */ private String request_status_code; /** * webhook请求返回的状态描述。 */ private String request_status_description; /** * 电话号码 */ private String msisdn; /** * 对请求成功支付的数组。 */ private List<Payments> payments; /** * 已启动但未成功授权的任何支付的数组。 */ private List<Payments> failed_payments; /** * 元数据 */ private String extra_data; /** * 国家的缩写 */ private String country_abbrv; public Long getCheckout_request_id() { return checkout_request_id; } public void setCheckout_request_id(Long checkout_request_id) { this.checkout_request_id = checkout_request_id; } public String getMerchant_transaction_id() { return merchant_transaction_id; } public void setMerchant_transaction_id(String merchant_transaction_id) { this.merchant_transaction_id = merchant_transaction_id; } public Double getRequest_amount() { return request_amount; } public void setRequest_amount(Double request_amount) { this.request_amount = request_amount; } public Double getOriginal_request_amount() { return original_request_amount; } public void setOriginal_request_amount(Double original_request_amount) { this.original_request_amount = original_request_amount; } public String getRequest_currency_code() { return request_currency_code; } public void setRequest_currency_code(String request_currency_code) { this.request_currency_code = request_currency_code; } public String getOriginal_request_currency_code() { return original_request_currency_code; } public void setOriginal_request_currency_code(String original_request_currency_code) { this.original_request_currency_code = original_request_currency_code; } public String getAccount_number() { return account_number; } public void setAccount_number(String account_number) { this.account_number = account_number; } public String getCurrency_code() { return currency_code; } public void setCurrency_code(String currency_code) { this.currency_code = currency_code; } public Double getAmount_paid() { return amount_paid; } public void setAmount_paid(Double amount_paid) { this.amount_paid = amount_paid; } public Double getService_charge_amount() { return service_charge_amount; } public void setService_charge_amount(Double service_charge_amount) { this.service_charge_amount = service_charge_amount; } public Date getRequest_date() { return request_date; } public void setRequest_date(String request_date) { try { SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH); this.request_date = format.parse(request_date); }catch (Exception e){ e.printStackTrace(); } } public String getService_code() { return service_code; } public void setService_code(String service_code) { this.service_code = service_code; } public String getRequest_status_code() { return request_status_code; } public void setRequest_status_code(String request_status_code) { this.request_status_code = request_status_code; } public String getRequest_status_description() { return request_status_description; } public void setRequest_status_description(String request_status_description) { this.request_status_description = request_status_description; } public String getMsisdn() { return msisdn; } public void setMsisdn(String msisdn) { this.msisdn = msisdn; } public List<Payments> getPayments() { return payments; } public void setPayments(List<Payments> payments) { this.payments = payments; } public List<Payments> getFailed_payments() { return failed_payments; } public void setFailed_payments(List<Payments> failed_payments) { this.failed_payments = failed_payments; } public String getExtra_data() { return extra_data; } public void setExtra_data(String extra_data) { this.extra_data = extra_data; } public String getCountry_abbrv() { return country_abbrv; } public void setCountry_abbrv(String country_abbrv) { this.country_abbrv = country_abbrv; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/CallbackResponse.java
New file @@ -0,0 +1,70 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 支付回调后的响应 */ public class CallbackResponse { /** * 数据库中唯一的纤维素ID */ private String checkout_request_id; /** * 商家为请求提出的唯一Id */ private String merchant_transaction_id; /** * 状态码,指示请求是否成功接收、失败或接受 */ private String status_code; /** * 状态码解释。 * 183表示成功 * 180表示拒绝付款。 * 188表示收到的款项。 */ private String status_description; /** * 返回的确认响应的唯一标识符。 */ private String receipt_number; public String getCheckout_request_id() { return checkout_request_id; } public void setCheckout_request_id(String checkout_request_id) { this.checkout_request_id = checkout_request_id; } public String getMerchant_transaction_id() { return merchant_transaction_id; } public void setMerchant_transaction_id(String merchant_transaction_id) { this.merchant_transaction_id = merchant_transaction_id; } public String getStatus_code() { return status_code; } public void setStatus_code(String status_code) { this.status_code = status_code; } public String getStatus_description() { return status_description; } public void setStatus_description(String status_description) { this.status_description = status_description; } public String getReceipt_number() { return receipt_number; } public void setReceipt_number(String receipt_number) { this.receipt_number = receipt_number; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/CheckoutRequest.java
New file @@ -0,0 +1,149 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; public class CheckoutRequest { /** * 电话号码 */ private Long msisdn; /** * 邮件地址 */ private String customerEmail; /** * 支付账户 */ private String accountNumber; /** * 名 */ private String customerFirstName; /** * 姓 */ private String customerLastName; /** * 支付金额 */ private Double requestAmount; /** * 订单号 */ private String merchantTransactionId; /** * 描述 */ private String requestDescription; /** * 回调地址 */ private String callbackUrl; /** * 在客户点击回到商家后,我们将客户重定向到哪里 */ private String pendingRedirectUrl; /** * 成功付款后将客户重定向到那里 */ private String successRedirectUrl; /** * 付款超时后的重定向 */ private String failRedirectUrl; public Long getMsisdn() { return msisdn; } public void setMsisdn(Long msisdn) { this.msisdn = msisdn; } public String getCustomerEmail() { return customerEmail; } public void setCustomerEmail(String customerEmail) { this.customerEmail = customerEmail; } public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } public String getCustomerFirstName() { return customerFirstName; } public void setCustomerFirstName(String customerFirstName) { this.customerFirstName = customerFirstName; } public String getCustomerLastName() { return customerLastName; } public void setCustomerLastName(String customerLastName) { this.customerLastName = customerLastName; } public Double getRequestAmount() { return requestAmount; } public void setRequestAmount(Double requestAmount) { this.requestAmount = requestAmount; } public String getMerchantTransactionId() { return merchantTransactionId; } public void setMerchantTransactionId(String merchantTransactionId) { this.merchantTransactionId = merchantTransactionId; } public String getRequestDescription() { return requestDescription; } public void setRequestDescription(String requestDescription) { this.requestDescription = requestDescription; } public String getCallbackUrl() { return callbackUrl; } public void setCallbackUrl(String callbackUrl) { this.callbackUrl = callbackUrl; } public String getPendingRedirectUrl() { return pendingRedirectUrl; } public void setPendingRedirectUrl(String pendingRedirectUrl) { this.pendingRedirectUrl = pendingRedirectUrl; } public String getSuccessRedirectUrl() { return successRedirectUrl; } public void setSuccessRedirectUrl(String successRedirectUrl) { this.successRedirectUrl = successRedirectUrl; } public String getFailRedirectUrl() { return failRedirectUrl; } public void setFailRedirectUrl(String failRedirectUrl) { this.failRedirectUrl = failRedirectUrl; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/Credentials.java
New file @@ -0,0 +1,49 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 凭证 * @author zhibing.pu * @date 2023/3/17 9:53 */ public class Credentials { /** * 用户名称 */ private String username; /** * 密码 */ private String password; public Credentials() { } public Credentials(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "Credentials{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/ExtraData.java
New file @@ -0,0 +1,27 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * @author zhibing.pu * @date 2023/3/17 10:13 */ public class ExtraData { /** * 回调地址 */ private String callbackUrl; public ExtraData() { } public ExtraData(String callbackUrl) { this.callbackUrl = callbackUrl; } public String getCallbackUrl() { return callbackUrl; } public void setCallbackUrl(String callbackUrl) { this.callbackUrl = callbackUrl; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/Packet.java
New file @@ -0,0 +1,132 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 实体包信息 * @author zhibing.pu * @date 2023/3/17 9:56 */ public class Packet { /** * 服务产品代码 */ private String serviceCode; /** * 进行支付的客户的手机号码。MSISDN应以国家代码开头,例如254xxxxxxxxx */ private String MSISDN; /** * 账号为收款账号。如果是手机号码,则应以国家代码开头,例如254xxxxxxxxx */ private String accountNumber; /** * 由银行为该事务生成的惟一transactionID。 */ private String payerTransactionID; /** * 客户支付的金额 */ private Double amount; /** * 备注信息 */ private String narration; /** * 付款人收到付款的日期。yyyy-mm-dd hh: mm: ss。 */ private String datePaymentReceived; /** * 额外数据 */ private ExtraData extraData; /** * 交易货币的 ISO 代码。 */ private String currencyCode; public String getServiceCode() { return serviceCode; } public void setServiceCode(String serviceCode) { this.serviceCode = serviceCode; } public String getMSISDN() { return MSISDN; } public void setMSISDN(String MSISDN) { this.MSISDN = MSISDN; } public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; } public String getPayerTransactionID() { return payerTransactionID; } public void setPayerTransactionID(String payerTransactionID) { this.payerTransactionID = payerTransactionID; } public Double getAmount() { return amount; } public void setAmount(Double amount) { this.amount = amount; } public String getNarration() { return narration; } public void setNarration(String narration) { this.narration = narration; } public String getDatePaymentReceived() { return datePaymentReceived; } public void setDatePaymentReceived(String datePaymentReceived) { this.datePaymentReceived = datePaymentReceived; } public ExtraData getExtraData() { return extraData; } public void setExtraData(ExtraData extraData) { this.extraData = extraData; } public String getCurrencyCode() { return currencyCode; } public void setCurrencyCode(String currencyCode) { this.currencyCode = currencyCode; } @Override public String toString() { return "Packet{" + "serviceCode='" + serviceCode + '\'' + ", MSISDN='" + MSISDN + '\'' + ", accountNumber='" + accountNumber + '\'' + ", payerTransactionID='" + payerTransactionID + '\'' + ", amount=" + amount + ", narration='" + narration + '\'' + ", datePaymentReceived='" + datePaymentReceived + '\'' + ", extraData=" + extraData + ", currencyCode='" + currencyCode + '\'' + '}'; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/PayOutload.java
New file @@ -0,0 +1,33 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * @author zhibing.pu * @date 2023/3/20 16:33 */ public class PayOutload { /** * 凭证 */ private Credentials credentials; /** * 实体包信息 */ private PayoutPacket packet; public Credentials getCredentials() { return credentials; } public void setCredentials(Credentials credentials) { this.credentials = credentials; } public PayoutPacket getPacket() { return packet; } public void setPacket(PayoutPacket packet) { this.packet = packet; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/Payload.java
New file @@ -0,0 +1,51 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; import java.util.List; /** * 退款实体 * @author zhibing.pu * @date 2023/3/17 9:51 */ public class Payload { /** * 凭证 */ private Credentials credentials; /** * 实体包信息 */ private List<Packet> packet; public Payload() { } public Payload(Credentials credentials, List<Packet> packet) { this.credentials = credentials; this.packet = packet; } public Credentials getCredentials() { return credentials; } public void setCredentials(Credentials credentials) { this.credentials = credentials; } public List<Packet> getPacket() { return packet; } public void setPacket(List<Packet> packet) { this.packet = packet; } @Override public String toString() { return "Payload{" + "credentials=" + credentials + ", packet=" + packet + '}'; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/Payments.java
New file @@ -0,0 +1,168 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; import java.util.Date; public class Payments { /** * 付款人的客户姓名 */ private String customer_name; /** * 客户付费购买的商家推荐 */ private String account_number; /** * 独特的纤维素特性 */ private String cpg_transaction_id; /** * 所支付的ISO货币代码 */ private String currency_code; /** * 支付方式客户支付,如Airtel */ private String payer_client_code; /** * 付款选项客户名称 */ private String payer_client_name; /** * 客户支付的金额 */ private Double amount_paid; /** * 服务代码支付给 */ private String service_code; /** * 付款和收款的时间 */ private Date date_payment_received; /** * 用户付费的手机号码 */ private String msisdn; /** * 为交易生成的MNO或银行的唯一id */ private String payer_transaction_id; /** * 付款的整体状态如下表所示 * 141 商户系统拒绝付款 * 139 商户待付款确认 * 140 商户接受的付款 * 138 付款请求已启动但失败 * 144 向商家交付但尚未确认成功的付款 * 219 付款已上报 */ private String hub_overall_status; /** * 由MNO、银行或信用卡收款人提供的付款说明。 */ private String payer_narration; public String getCustomer_name() { return customer_name; } public void setCustomer_name(String customer_name) { this.customer_name = customer_name; } public String getAccount_number() { return account_number; } public void setAccount_number(String account_number) { this.account_number = account_number; } public String getCpg_transaction_id() { return cpg_transaction_id; } public void setCpg_transaction_id(String cpg_transaction_id) { this.cpg_transaction_id = cpg_transaction_id; } public String getCurrency_code() { return currency_code; } public void setCurrency_code(String currency_code) { this.currency_code = currency_code; } public String getPayer_client_code() { return payer_client_code; } public void setPayer_client_code(String payer_client_code) { this.payer_client_code = payer_client_code; } public String getPayer_client_name() { return payer_client_name; } public void setPayer_client_name(String payer_client_name) { this.payer_client_name = payer_client_name; } public Double getAmount_paid() { return amount_paid; } public void setAmount_paid(Double amount_paid) { this.amount_paid = amount_paid; } public String getService_code() { return service_code; } public void setService_code(String service_code) { this.service_code = service_code; } public Date getDate_payment_received() { return date_payment_received; } public void setDate_payment_received(Date date_payment_received) { this.date_payment_received = date_payment_received; } public String getMsisdn() { return msisdn; } public void setMsisdn(String msisdn) { this.msisdn = msisdn; } public String getPayer_transaction_id() { return payer_transaction_id; } public void setPayer_transaction_id(String payer_transaction_id) { this.payer_transaction_id = payer_transaction_id; } public String getHub_overall_status() { return hub_overall_status; } public void setHub_overall_status(String hub_overall_status) { this.hub_overall_status = hub_overall_status; } public String getPayer_narration() { return payer_narration; } public void setPayer_narration(String payer_narration) { this.payer_narration = payer_narration; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/Payout.java
New file @@ -0,0 +1,54 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 退款 * @author zhibing.pu * @date 2023/3/17 9:49 */ public class Payout { /** * 国家代码 */ private String countryCode; /** * 接口类型 */ private String function; /** * 参数实体 */ private Payload payload; public Payout() { } public Payout(String countryCode, String function, Payload payload) { this.countryCode = countryCode; this.function = function; this.payload = payload; } public String getCountryCode() { return countryCode; } public void setCountryCode(String countryCode) { this.countryCode = countryCode; } public String getFunction() { return function; } public void setFunction(String function) { this.function = function; } public Payload getPayload() { return payload; } public void setPayload(Payload payload) { this.payload = payload; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/PayoutCallbackRequest.java
New file @@ -0,0 +1,45 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 转账回调请求 * @author zhibing.pu * @date 2023/3/20 16:31 */ public class PayoutCallbackRequest { /** * 国家代码 */ private String countryCode; /** * 调用函数 */ private String function; /** * 数据 */ private PayOutload payload; public String getCountryCode() { return countryCode; } public void setCountryCode(String countryCode) { this.countryCode = countryCode; } public String getFunction() { return function; } public void setFunction(String function) { this.function = function; } public PayOutload getPayload() { return payload; } public void setPayload(PayOutload payload) { this.payload = payload; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/PayoutCallbackResponse.java
New file @@ -0,0 +1,33 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 转账回调反馈 * @author zhibing.pu * @date 2023/3/20 16:40 */ public class PayoutCallbackResponse { /** * 认证状态及说明 */ private AuthStatus authStatus; /** * */ private Results results; public AuthStatus getAuthStatus() { return authStatus; } public void setAuthStatus(AuthStatus authStatus) { this.authStatus = authStatus; } public Results getResults() { return results; } public void setResults(Results results) { this.results = results; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/PayoutPacket.java
New file @@ -0,0 +1,93 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * 实体包信息 * @author zhibing.pu * @date 2023/3/17 9:56 */ public class PayoutPacket { /** * 返回状态 */ private String statusCode; /** * 状态说明 */ private String statusDescription; /** * 正在支付账号。如果是手机号码,应该以国家代码开头,例如2547xxxxxxxx */ private String beepTransactionID; /** * 由银行为该事务生成的惟一transactionID。 */ private String payerTransactionID; /** * 客户支付的金额。 */ private String receiptNumber; /** * 正在付款的叙述。 */ private String receiverNarration; public String getStatusCode() { return statusCode; } public void setStatusCode(String statusCode) { this.statusCode = statusCode; } public String getStatusDescription() { return statusDescription; } public void setStatusDescription(String statusDescription) { this.statusDescription = statusDescription; } public String getBeepTransactionID() { return beepTransactionID; } public void setBeepTransactionID(String beepTransactionID) { this.beepTransactionID = beepTransactionID; } public String getPayerTransactionID() { return payerTransactionID; } public void setPayerTransactionID(String payerTransactionID) { this.payerTransactionID = payerTransactionID; } public String getReceiptNumber() { return receiptNumber; } public void setReceiptNumber(String receiptNumber) { this.receiptNumber = receiptNumber; } public String getReceiverNarration() { return receiverNarration; } public void setReceiverNarration(String receiverNarration) { this.receiverNarration = receiverNarration; } @Override public String toString() { return "PayoutPacket{" + "statusCode='" + statusCode + '\'' + ", statusDescription='" + statusDescription + '\'' + ", beepTransactionID='" + beepTransactionID + '\'' + ", payerTransactionID='" + payerTransactionID + '\'' + ", receiptNumber='" + receiptNumber + '\'' + ", receiverNarration='" + receiverNarration + '\'' + '}'; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/PayoutResponse.java
New file @@ -0,0 +1,35 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; import java.util.List; /** * 转账回调反馈 * @author zhibing.pu * @date 2023/3/20 16:40 */ public class PayoutResponse { /** * 认证状态及说明 */ private AuthStatus authStatus; /** * */ private List<Results> results; public AuthStatus getAuthStatus() { return authStatus; } public void setAuthStatus(AuthStatus authStatus) { this.authStatus = authStatus; } public List<Results> getResults() { return results; } public void setResults(List<Results> results) { this.results = results; } } ManagementIGOTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/Tingg/model/Results.java
New file @@ -0,0 +1,56 @@ package com.stylefeng.guns.modular.system.util.Tingg.model; /** * @author zhibing.pu * @date 2023/3/20 16:55 */ public class Results { /** * beep流水ID */ private String beepTransactionID; /** * 交易id */ private String payerTransactionID; /** * 188 */ private String statusCode; /** * 状态说明 */ private String statusDescription; public String getBeepTransactionID() { return beepTransactionID; } public void setBeepTransactionID(String beepTransactionID) { this.beepTransactionID = beepTransactionID; } public String getPayerTransactionID() { return payerTransactionID; } public void setPayerTransactionID(String payerTransactionID) { this.payerTransactionID = payerTransactionID; } public String getStatusCode() { return statusCode; } public void setStatusCode(String statusCode) { this.statusCode = statusCode; } public String getStatusDescription() { return statusDescription; } public void setStatusDescription(String statusDescription) { this.statusDescription = statusDescription; } } ManagementIGOTravel/guns-admin/src/main/resources/application.yml
@@ -127,4 +127,11 @@ from: southwindservice@gmail.com # 发送方邮件,配在yml中可方便更改 template-path: /usr/local/nginx/html/mailbox/ --- #支付回调地址 #正式环境 #callbackPath: https://okyueche.com:443/user #测试环境 callbackPath: http://182.160.16.251:8010 ---