拉卡拉支付调试修正
This commit is contained in:
parent
81e4341276
commit
7f7430291a
@ -232,6 +232,15 @@ public interface ShopService {
|
|||||||
@GetMapping(value = "/admin/shop/shop-store-base/get")
|
@GetMapping(value = "/admin/shop/shop-store-base/get")
|
||||||
CommonResult getStoreBase(@RequestParam(name = "store_id", required = false) Integer store_id);
|
CommonResult getStoreBase(@RequestParam(name = "store_id", required = false) Integer store_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取店铺的拉卡拉商户号和终端号(仅仅两个字段)
|
||||||
|
* @param store_id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping(value = "/admin/shop/shop-store-base/lkl-merchant-term/get")
|
||||||
|
ShopStoreBase getLklMerchantNoAndTermNo(@RequestParam(name = "store_id") Integer store_id);
|
||||||
|
|
||||||
|
|
||||||
@GetMapping(value = "/admin/shop/shop-order-base/handleIsBuy")
|
@GetMapping(value = "/admin/shop/shop-order-base/handleIsBuy")
|
||||||
Map handleIsBuy(@RequestParam(name = "product_id") Long product_id);
|
Map handleIsBuy(@RequestParam(name = "product_id") Long product_id);
|
||||||
|
|
||||||
|
|||||||
@ -114,4 +114,10 @@ public class ShopStoreBase implements Serializable {
|
|||||||
@ApiModelProperty(value = "所属分站:0-总站")
|
@ApiModelProperty(value = "所属分站:0-总站")
|
||||||
private Integer subsite_id;
|
private Integer subsite_id;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "关联拉卡拉的商户号")
|
||||||
|
private String lkl_merchant_no;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "关联拉卡拉的终端号码")
|
||||||
|
private String lkl_term_no;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,12 +11,15 @@ package com.suisung.mall.pay.service;
|
|||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import com.suisung.mall.common.pojo.res.PayAccRespFieldsRes;
|
import com.suisung.mall.common.pojo.res.PayAccRespFieldsRes;
|
||||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||||
|
import org.springframework.data.util.Pair;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
public interface LakalaService {
|
public interface LakalaService {
|
||||||
|
|
||||||
|
Boolean initLKLSDK();
|
||||||
|
|
||||||
JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId);
|
JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,4 +38,12 @@ public interface LakalaService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark);
|
JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉卡拉查询商户号和终端号
|
||||||
|
*
|
||||||
|
* @param storeId 店铺 id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Pair<String, String> getLklMerchantNoAndTermNo(String storeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,8 @@ import com.suisung.mall.common.utils.I18nUtil;
|
|||||||
import com.suisung.mall.pay.service.LakalaService;
|
import com.suisung.mall.pay.service.LakalaService;
|
||||||
import com.suisung.mall.pay.utils.LakalaUtil;
|
import com.suisung.mall.pay.utils.LakalaUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.util.Pair;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -32,18 +34,49 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class LakalaServiceImpl implements LakalaService {
|
public class LakalaServiceImpl implements LakalaService {
|
||||||
|
private static volatile boolean init = false;
|
||||||
|
|
||||||
|
@Value("${lakala.server_url}")
|
||||||
|
private String serverUrl; //服务地址
|
||||||
|
@Value("${lakala.app_id}")
|
||||||
|
private String appId; // 拉卡拉appId
|
||||||
|
@Value("${lakala.serial_no}")
|
||||||
|
private String serialNo; // 你的证书序列号
|
||||||
|
@Value("${lakala.api_pri_key_path}")
|
||||||
|
private String priKeyPath; //商户私钥信息地址
|
||||||
|
@Value("${lakala.lkl_platform_cer_path}")
|
||||||
|
private String lklCerPath; //拉卡拉支付平台证书地址
|
||||||
|
@Value("${lakala.lkl_platform_cer_path}")
|
||||||
|
private String lklNotifyCerPath; //拉卡拉支付平台证书地址2(用于拉卡拉通知验签)
|
||||||
|
|
||||||
|
// 可选的两个参数
|
||||||
|
@Value("${lakala.merchant_no}")
|
||||||
|
public String merchantNo; // 拉卡拉分配的商户号
|
||||||
|
@Value("${lakala.term_no}")
|
||||||
|
public String termNo; // 拉卡拉分配的终端号码
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 拉卡拉SDK
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean initLKLSDK() {
|
||||||
|
if (!init) {
|
||||||
|
return LakalaUtil.initLKLSDK(appId, serialNo, priKeyPath, lklCerPath, lklNotifyCerPath, serverUrl);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public cn.hutool.json.JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) {
|
public cn.hutool.json.JSONObject transPreOrder(HttpServletRequest request, HttpServletResponse response, String orderId) {
|
||||||
// 1. 配置初始化
|
// 1. 配置初始化
|
||||||
LakalaUtil.doInit();
|
initLKLSDK();
|
||||||
|
|
||||||
//2. 装配数据
|
//2. 装配数据
|
||||||
/*** 微信主扫场景示例 */
|
/*** 微信主扫场景示例 */
|
||||||
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
|
V3LabsTransPreorderRequest v3LabsTransPreorderWechatReq = new V3LabsTransPreorderRequest();
|
||||||
v3LabsTransPreorderWechatReq.setMerchantNo(LakalaUtil.merchantNo);
|
v3LabsTransPreorderWechatReq.setMerchantNo(merchantNo);
|
||||||
v3LabsTransPreorderWechatReq.setTermNo(LakalaUtil.termNo);
|
v3LabsTransPreorderWechatReq.setTermNo(termNo);
|
||||||
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
|
v3LabsTransPreorderWechatReq.setOutTradeNo(orderId);
|
||||||
v3LabsTransPreorderWechatReq.setSubject("油麦菜5斤装特惠");
|
v3LabsTransPreorderWechatReq.setSubject("油麦菜5斤装特惠");
|
||||||
v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
|
v3LabsTransPreorderWechatReq.setAccountType("WECHAT");
|
||||||
@ -94,13 +127,13 @@ public class LakalaServiceImpl implements LakalaService {
|
|||||||
@Override
|
@Override
|
||||||
public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
|
public JSONObject transPreOrder(String merchantNo, String termNo, String xcxAppId, String openId, String orderId, String subject, String totalAmount, String notifyURL, String requestIP, String remark) {
|
||||||
// 1. 配置初始化
|
// 1. 配置初始化
|
||||||
LakalaUtil.doInit();
|
LakalaUtil.initLKLSDK(appId, serialNo, priKeyPath, lklCerPath, lklNotifyCerPath, serverUrl);
|
||||||
|
|
||||||
if (StrUtil.isBlank(merchantNo)) {
|
if (StrUtil.isBlank(merchantNo)) {
|
||||||
merchantNo = LakalaUtil.merchantNo;
|
merchantNo = this.merchantNo;
|
||||||
}
|
}
|
||||||
if (StrUtil.isBlank(termNo)) {
|
if (StrUtil.isBlank(termNo)) {
|
||||||
termNo = LakalaUtil.termNo;
|
termNo = this.termNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
//2. 装配数据
|
//2. 装配数据
|
||||||
@ -149,5 +182,16 @@ public class LakalaServiceImpl implements LakalaService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉卡拉查询商户号和终端号
|
||||||
|
*
|
||||||
|
* @param storeId 店铺 id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Pair<String, String> getLklMerchantNoAndTermNo(String storeId) {
|
||||||
|
return Pair.of("","");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import com.suisung.mall.common.modules.order.ShopOrderInfo;
|
|||||||
import com.suisung.mall.common.modules.order.ShopOrderReturn;
|
import com.suisung.mall.common.modules.order.ShopOrderReturn;
|
||||||
import com.suisung.mall.common.modules.pay.*;
|
import com.suisung.mall.common.modules.pay.*;
|
||||||
import com.suisung.mall.common.modules.pay.dto.ItemActivityInfoDTO;
|
import com.suisung.mall.common.modules.pay.dto.ItemActivityInfoDTO;
|
||||||
|
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
import com.suisung.mall.common.utils.LogUtil;
|
import com.suisung.mall.common.utils.LogUtil;
|
||||||
@ -590,21 +591,30 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
|||||||
WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
|
WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
|
||||||
logger.info("微信支付配置值:{}", JSONUtil.toJsonStr(wxPayApiConfig));
|
logger.info("微信支付配置值:{}", JSONUtil.toJsonStr(wxPayApiConfig));
|
||||||
|
|
||||||
// https://mall.gpxscs.cn/mobile/pay/index
|
Map data = new HashMap();
|
||||||
|
data.put("code", 1);
|
||||||
|
data.put("data", new Object());
|
||||||
|
|
||||||
|
// 这里获取店铺的拉卡拉的商户号和终端号码
|
||||||
|
ShopStoreBase shopStoreBase = shopService.getLklMerchantNoAndTermNo(payConsumeTrade.getStore_id());
|
||||||
|
if (shopStoreBase == null) {
|
||||||
|
data.put("message", "获取店铺信息失败!");
|
||||||
|
setResponseBody(response, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// domain: https://mall.gpxscs.cn/mobile/pay/index
|
||||||
String domain = wxPayApiConfig.getDomain();
|
String domain = wxPayApiConfig.getDomain();
|
||||||
String requestIP = IpKit.getRealIp(request);
|
String requestIP = IpKit.getRealIp(request);
|
||||||
String notifyUrl = domain + "/lkl_wxPay_notify_url";
|
String notifyUrl = domain + "/lkl_wxPay_notify_url";
|
||||||
|
|
||||||
// 拉卡拉预支付返回参数
|
// 拉卡拉预支付返回参数
|
||||||
cn.hutool.json.JSONObject lakalaRespJSON = lakalaService.transPreOrder(null, null,
|
cn.hutool.json.JSONObject lakalaRespJSON = lakalaService.transPreOrder(shopStoreBase.getLkl_merchant_no(), shopStoreBase.getLkl_term_no(),
|
||||||
appId, openId, out_trade_no, subject, total_fee,
|
appId, openId, out_trade_no, subject, total_fee,
|
||||||
notifyUrl,
|
notifyUrl,
|
||||||
requestIP, trade_remark);
|
requestIP, trade_remark);
|
||||||
|
|
||||||
// logger.info("拉卡拉预支付返回参数:{}", JSONUtil.toJsonStr(field));
|
// logger.info("拉卡拉预支付返回参数:{}", JSONUtil.toJsonStr(field));
|
||||||
Map data = new HashMap();
|
|
||||||
data.put("code", 1);
|
|
||||||
data.put("data", new Object());
|
|
||||||
|
|
||||||
if (lakalaRespJSON == null || !lakalaRespJSON.getStr("code").equals("BBS00000")) {
|
if (lakalaRespJSON == null || !lakalaRespJSON.getStr("code").equals("BBS00000")) {
|
||||||
data.put("message", lakalaRespJSON.getStr("msg"));
|
data.put("message", lakalaRespJSON.getStr("msg"));
|
||||||
@ -1256,7 +1266,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
|
|||||||
public String lklNotifyUrl(HttpServletRequest request) {
|
public String lklNotifyUrl(HttpServletRequest request) {
|
||||||
Map<String, String> params;
|
Map<String, String> params;
|
||||||
try {
|
try {
|
||||||
LakalaUtil.doInit();
|
lakalaService.initLKLSDK();
|
||||||
|
|
||||||
// spring-boot 2.x 直接调用读取请求体并验签方法,返回请求体
|
// spring-boot 2.x 直接调用读取请求体并验签方法,返回请求体
|
||||||
String body = LKLSDK.notificationHandle(request);
|
String body = LKLSDK.notificationHandle(request);
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -35,57 +36,12 @@ import java.util.Map;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class LakalaUtil {
|
public class LakalaUtil {
|
||||||
|
|
||||||
private static volatile boolean init = false;
|
|
||||||
|
|
||||||
private static volatile NativePayService wxV3Service;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务地址
|
* 初始化 拉卡拉 SDK(全局只需设置一次)
|
||||||
*/
|
|
||||||
@Value("${lakala.server_url}")
|
|
||||||
private static String serverUrl;
|
|
||||||
@Value("${lakala.app_id}")
|
|
||||||
private static String appId; // 拉卡拉appId
|
|
||||||
@Value("${lakala.merchant_no}")
|
|
||||||
public static String merchantNo;
|
|
||||||
@Value("${lakala.serial_no}")
|
|
||||||
private static String serialNo; // 你的证书序列号
|
|
||||||
@Value("${lakala.term_no}")
|
|
||||||
public static String termNo;
|
|
||||||
/**
|
|
||||||
* 商户私钥信息地址
|
|
||||||
*/
|
|
||||||
@Value("${lakala.api_pri_key_path}")
|
|
||||||
private static String priKeyPath;
|
|
||||||
/**
|
|
||||||
* 拉卡拉支付平台证书地址
|
|
||||||
*/
|
|
||||||
@Value("${lakala.lkl_platform_cer_path}")
|
|
||||||
private static String lklCerPath;
|
|
||||||
/**
|
|
||||||
* 拉卡拉支付平台证书地址2(用于拉卡拉通知验签)
|
|
||||||
*/
|
|
||||||
@Value("${lakala.lkl_platform_cer_path}")
|
|
||||||
private static String lklNotifyCerPath;
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* @Description: 初始化设置商户公共参数(全局只需设置一次)
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static void doInit() {
|
|
||||||
if (!init) {
|
|
||||||
init = initLKLSDK();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化 拉卡拉 SDK
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean initLKLSDK() {
|
public static boolean initLKLSDK(String appId, String serialNo, String priKeyPath, String lklCerPath, String lklNotifyCerPath, String serverUrl) {
|
||||||
Config2 config = new Config2();
|
Config2 config = new Config2();
|
||||||
config.setAppId(appId);
|
config.setAppId(appId);
|
||||||
config.setSerialNo(serialNo);
|
config.setSerialNo(serialNo);
|
||||||
|
|||||||
@ -232,5 +232,16 @@ public class ShopStoreBaseController extends BaseControllerImpl {
|
|||||||
public CommonResult storeBusinessTypeList() {
|
public CommonResult storeBusinessTypeList() {
|
||||||
return transportBaseService.storeBusinessTypeList();
|
return transportBaseService.storeBusinessTypeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取店铺的拉卡拉商户号和终端号(仅仅两个字段)
|
||||||
|
* @param store_id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@ApiOperation(value = "获取店铺的拉卡拉商户号和终端号(仅仅两个字段)", notes = "获取店铺的拉卡拉商户号和终端号(仅仅两个字段)")
|
||||||
|
@PostMapping(value = "/lkl-merchant-term/get")
|
||||||
|
public ShopStoreBase getLklMerchantNoAndTermNo(@RequestParam(name = "store_id") Integer store_id){
|
||||||
|
return shopStoreBaseService.getLklMerchantNoAndTermNo(store_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -127,4 +127,11 @@ public interface ShopStoreBaseService extends IBaseService<ShopStoreBase> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
IPage<Map> getNearShop2(String provinceId,String cityId, String countyId, String userLng,String userLat, Integer categoryId,Integer subsiteId, String storeName, Integer pageNum, Integer pageSize);
|
IPage<Map> getNearShop2(String provinceId,String cityId, String countyId, String userLng,String userLat, Integer categoryId,Integer subsiteId, String storeName, Integer pageNum, Integer pageSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取店铺的拉卡拉商户号和终端号(仅仅两个字段)
|
||||||
|
* @param storeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ShopStoreBase getLklMerchantNoAndTermNo(Integer storeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2908,6 +2908,29 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
|||||||
return shopStoreBaseMapper.getNearShop2(new Page<>(pageNum, pageSize), params);
|
return shopStoreBaseMapper.getNearShop2(new Page<>(pageNum, pageSize), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取店铺的拉卡拉商户号和终端号(仅仅两个字段)
|
||||||
|
*
|
||||||
|
* @param storeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ShopStoreBase getLklMerchantNoAndTermNo(Integer storeId) {
|
||||||
|
if (ObjectUtil.isEmpty(storeId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryWrapper<ShopStoreBase> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("store_id", storeId);
|
||||||
|
queryWrapper.select("lkl_merchant_no", "lkl_term_no");
|
||||||
|
ShopStoreBase shopStoreBase = getOne(queryWrapper);
|
||||||
|
if (ObjectUtil.isEmpty(shopStoreBase)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shopStoreBase;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 store_slide 字段
|
* 处理 store_slide 字段
|
||||||
*
|
*
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
, user_id, store_name, store_grade_id, store_logo, store_slogan, store_domain, store_area, store_district_id,
|
, user_id, store_name, store_grade_id, store_logo, store_slogan, store_domain, store_area, store_district_id,
|
||||||
store_address, store_latitude, store_longitude, store_is_selfsupport, store_type, store_is_open, shop_parent_id,
|
store_address, store_latitude, store_longitude, store_is_selfsupport, store_type, store_is_open, shop_parent_id,
|
||||||
store_category_id, store_state_id, store_time, store_end_time, product_category_ids, store_o2o_tags,
|
store_category_id, store_state_id, store_time, store_end_time, product_category_ids, store_o2o_tags,
|
||||||
store_o2o_flag, store_o2o_merchant_id, store_circle, subsite_id
|
store_o2o_flag, store_o2o_merchant_id, store_circle, subsite_id, lkl_merchant_no, lkl_term_no
|
||||||
</sql>
|
</sql>
|
||||||
<select id="statisticState" resultType="java.util.Map">
|
<select id="statisticState" resultType="java.util.Map">
|
||||||
SELECT store_state_id state,
|
SELECT store_state_id state,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user