之前写过支付宝,微信app支付开发,现在将支付宝的退款,微信退款,支付宝提现功能贴出来。
微信提现功能之前看了官方文档。好像不太好实现,所以换了一个思路。商户转账到用户端,
但是企业对用户转账有限制,需要该商户入住超过90天,需要该商户连续一个月有正常收入才能开通该功能。
所以现在我每天给商户端转账1元。等开通后在贴出代码。
以下是支付宝退款,申请提现代码:
/**
* 支付宝退款交易申请
* @param req
* @param res
* @return
*/
@OperLog(logDescription="支付宝退款交易申请")
@RequestMapping(value="refundPay",method=RequestMethod.POST)
@ResponseBody
public Map<String, Object> refundPay(HttpServletRequest req,
HttpServletResponse res){
res.setCharacterEncoding("UTF-8");
String createNum = req.getParameter("complete_order_details_number");
String refundAmount = req.getParameter("refundAmount");
String refundReason = StringUtils.isNullString(req.getParameter("refundReason"))?"用户申请退款":req.getParameter("refundReason");
CompleteOrderDetails completeOrderDetails = completeOrderDetailsService.selectCompleteOrderDetailsById(createNum);
if(StringUtils.isObjectNull(completeOrderDetails))
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "当前订单不存在", PathCommon.ERROR);
String stagePrice = completeOrderDetails.getComplete_order_details_stage_price();
if(StringUtils.isNullString(stagePrice) || StringUtils.isNullString(refundAmount))
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "申请的退款金额不存在!", PathCommonEnum.ERROR.getValue());
//如果左边比右边大,则退款金额失败
if(pareTo(Double.parseDouble(refundAmount), Double.parseDouble(stagePrice)) == 1)
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "申请退款的金额超出付款过的金额!", PathCommonEnum.ERROR.getValue());
//上面的判断方法用的工具类是自己写的。并非是阿里提供。
AlipayClient alipayClient = new DefaultAlipayClient("/gateway.do", AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.input_charset, AlipayConfig.ALIPAY_PUBLIC_KEY, "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
model.setOutTradeNo(createNum);//12345678900
//model.setTradeNo("1234567890000");//支付宝交易号 和上面的2选1即可
model.setRefundAmount(refundAmount);//需要退款的金额,该金额不能大于订单金额,单位为元,支持两位小数
model.setRefundReason(refundReason);//退款的原因说明
request.setBizModel(model);
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
//同意申请退款
refundService.updateSureRefund(completeOrderDetails.getComplete_order_only_md5());
return JsonMethod.setJsonMethod(PathKeyEnum.SUCCESS.getKey(), PathKeyEnum.SUCCESS.getValue(), response.getBody());
}
} catch (Exception e) {
LogComm.setLog(e.getMessage()+",退款抛出异常");
}
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), PathKeyEnum.ERROR.getValue(), PathCommon.ERROR);
}
/**
* 支付宝申请提现 该提现功能是针对后台管理系统申请提现,然后支付宝商家端自动转账到该商家
* @param session
* @param req
* @param res
* @return
*/
@OperLog(logDescription="支付宝申请提现")
@RequestMapping(value="zhuanzhang",method={RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public Map<String, Object> zhuanzhang(HttpSession session,HttpServletRequest req,
HttpServletResponse res){
res.setCharacterEncoding("UTF-8");
String assembly_only_md5 = super.getMasterAssemblyMD5(session);
if(StringUtils.isNullString(assembly_only_md5))
return JsonMethod.setJsonMethod(PathKeyEnum.LOGINFAILURE.getKey(), PathKeyEnum.LOGINFAILURE.getValue(), PathCommonEnum.ERROR.getValue());
AssemblyWallet assemblyWallet = assemblyWalletService.selectAssemblyWalletInfo(assembly_only_md5);
if(StringUtils.isObjectNull(assemblyWallet))
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), PathKeyEnum.ERROR.getValue(), PathCommonEnum.ERROR.getValue());
String curPrice = req.getParameter("curPrice");//转账的金额
String realName = req.getParameter("realName");//可以自己填写真是姓名
if(StringUtils.isNullString(curPrice) ||
StringUtils.isNullString(realName))
return JsonMethod.setJsonMethod(PathKeyEnum.PARAMERROR.getKey(), PathKeyEnum.PARAMERROR.getValue(), PathCommonEnum.ERROR.getValue());
if(pareTo(Double.parseDouble(curPrice), Double.parseDouble(assemblyWallet.getAssembly_price())) == 1)
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "申请提现的错误,请重新申请提现!", PathCommonEnum.ERROR.getValue());
if(pareTo(Double.parseDouble(curPrice), Double.parseDouble("0.1")) == -1)
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "提现金额不得小于0.1元!", PathCommonEnum.ERROR.getValue());
if(pareTo(Double.parseDouble(curPrice), Double.parseDouble("10000")) == 1)
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "单笔提现不得超过10000元!", PathCommonEnum.ERROR.getValue());
//转账到商家的支付宝。即:商户 > 个人支付宝
AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
String curOrderNum = CommonUtils.createNum();
model.setOutBizNo(curOrderNum);//生成新的订单编号
model.setPayeeType("ALIPAY_LOGONID");
//账号数据从数据库里获取
model.setPayeeAccount(assemblyWallet.getAlipay_account());//转账接收的账户
//最低0.1元
model.setAmount(curPrice);//转账金额
model.setPayerShowName("");//商户端的名称
//接受方真是姓名
model.setPayeeRealName(realName);
try {
return alipayZhuanZhang(model, assembly_only_md5, curPrice, curOrderNum);
} catch (Exception e) {
// TODO Auto-generated catch block
LogComm.setLog("整装公司后台提现抛出异常:" + e.getMessage());
}
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "提现失败,请稍后再试!", PathCommonEnum.ERROR.getValue());
}
/**
* 调用阿里转账api
* @param model
* @return
*/
private Map<String, Object> alipayZhuanZhang(AlipayFundTransToaccountTransferModel model,
String assembly_only_md5,String curPrice,String curOrderNum){
AlipayClient alipayClient = new DefaultAlipayClient("/gateway.do", AlipayConfig.APP_ID, AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.input_charset, AlipayConfig.ALIPAY_PUBLIC_KEY, "RSA2");
AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
request.setBizModel(model);
try {
AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
String result = response.getBody();
if (response.isSuccess()) {
//修改商家支付宝余额
assemblyWalletService.updateAssemblyWalletInfo(assembly_only_md5, curPrice);
//记录商家提现数据
assemblyWalletOrderService.insertAssemblyWalletOrder(curOrderNum, curPrice, assembly_only_md5);
return JsonMethod.setJsonMethod(PathKeyEnum.SUCCESS.getKey(), PathKeyEnum.SUCCESS.getValue(), PathCommonEnum.SUCCESS.getValue());
}else{
JSONObject jsonObject = JSONObject.parseObject(result);
String out_biz_no = jsonObject.getJSONObject("alipay_fund_trans_toaccount_transfer_response").getString("out_biz_no");
AlipayFundTransOrderQueryModel queryModel = new AlipayFundTransOrderQueryModel();
queryModel.setOutBizNo(out_biz_no);
AlipayFundTransOrderQueryRequest req = new AlipayFundTransOrderQueryRequest();
req.setBizModel(model);
AlipayFundTransOrderQueryResponse res = alipayClient.execute(req);
if(res.isSuccess()){
//修改商家支付宝余额
assemblyWalletService.updateAssemblyWalletInfo(assembly_only_md5, curPrice);
assemblyWalletOrderService.insertAssemblyWalletOrder(curOrderNum, curPrice, assembly_only_md5);
return JsonMethod.setJsonMethod(PathKeyEnum.SUCCESS.getKey(), PathKeyEnum.SUCCESS.getValue(), PathCommonEnum.SUCCESS.getValue());
}else{
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), response.getSubMsg(), PathCommonEnum.ERROR.getValue());
}
}
} catch (Exception e) {
// TODO: handle exception
LogComm.setLog("申请提现抛出异常:" + e.getMessage());
}
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), PathKeyEnum.ERROR.getValue(), PathCommonEnum.ERROR.getValue());
}
下面是微信退款,
/**
* 微信退款交易申请
* @param req
* @param res
* @return
*/
@OperLog(logDescription="微信退款交易申请")
@RequestMapping(value="refundPay",method=RequestMethod.POST)
@ResponseBody
public Map<String, Object> refundPay(HttpServletRequest req,
HttpServletResponse res){
res.setCharacterEncoding("UTF-8");
String createNum = req.getParameter("complete_order_details_number");
String refundAmount = req.getParameter("refundAmount");
CompleteOrderDetails completeOrderDetails = completeOrderDetailsService.selectCompleteOrderDetailsById(createNum);
if(StringUtils.isObjectNull(completeOrderDetails))
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "当前订单不存在", PathCommon.ERROR);
String stagePrice = completeOrderDetails.getComplete_order_details_stage_price();
if(StringUtils.isNullString(stagePrice) || StringUtils.isNullString(refundAmount))
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "申请的退款金额不存在!", PathCommonEnum.ERROR.getValue());
//如果左边比右边大,则退款金额失败
if(pareTo(Double.parseDouble(refundAmount), Double.parseDouble(stagePrice)) == 1)
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "申请退款的金额超出付款过的金额!", PathCommonEnum.ERROR.getValue());
try {
WxPayUtilConfig config = new WxPayUtilConfig();
WXPay wxPay = new WXPay(config);
Map<String, String> param = new HashMap<String, String>();
param.put("appid", config.getAppID());
//内容描述可通过前端app传递过来.
param.put("mch_id", config.getMchID());
param.put("nonce_str", WXPayUtil.generateNonceStr());
//param.put("notify_url", WXPayCommonPath.REFUND_NOTIFYURL);
param.put("out_refund_no", createNum);
param.put("out_trade_no", createNum);
param.put("refund_fee",String.valueOf((int)CommonUtils.mul(Double.parseDouble(refundAmount), 100.00)));
param.put("total_fee", String.valueOf((int)CommonUtils.mul(Double.parseDouble(completeOrderDetails.getComplete_order_details_stage_price()), 100.00)));//金额 以分为单位.我这边是测试数据.
//param.put("transaction_id", "420000028401150238168840");
String sign = WXPayUtil.generateSignature(param,WXPayCommonPath.API_KEY);
param.put("sign", sign);
//WXPayUtil.generateSignedXml(param, WXPayCommonPath.API_KEY);
Map<String, String> returnMap = wxPay.refund(param);
if("SUCCESS".equals(returnMap.get("return_code"))){
refundService.updateSureRefund(completeOrderDetails.getComplete_order_only_md5());
return JsonMethod.setJsonMethod(PathKeyEnum.SUCCESS.getKey(), "退款成功", PathCommonEnum.SUCCESS.getValue());
}
} catch (Exception e) {
// TODO: handle exception
LogComm.setLog("微信退款交易申请抛出异常:" + e.getMessage());
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), "退款失败,微信退款api抛出异常", PathCommonEnum.ERROR.getValue());
}
return JsonMethod.setJsonMethod(PathKeyEnum.ERROR.getKey(), PathKeyEnum.ERROR.getValue(), PathCommonEnum.ERROR.getValue());
}
微信提现:官方文档看到了是红包形式的转账。限制5K,
然后我研究了商户对银行卡转账。等待开通功能。等好了之后在贴出来。
上面退款功能:
用户在app端发起退款申请,
后台针对该数据同意/拒绝退款,。同意就是上面的代码。
提现是商家后台输入金额,支付宝账号,等。然后确定,商户 > 商家(个人支付宝账号。)
以上功能是可以通过的。已上线。
/04/11:今天整个项目测试中,发现了一个支付宝退款bug,故现在写下来:
支付宝退款分两种,
1:部分退款
2:全额退款
部分退款:
model.setOutRequestNo("TK"+CommonUtils.createNum());//部分退款下,该字段需要传递
该值是属于自定义字段,如果是部分退款的话,则该值必须填写。可以进行判断,提现的金额是否小于付款的金额。
全额退款:
因为全额退款会触发通知,支付宝的回调通知会默认使用你支付时的回调链接。
所以要在回调的方法那做判断处理
String refund_fee = params.get("refund_fee");
String gmt_refund = params.get("gmt_refund");
以上2个字段只有退款时会存在,支付时 则该值为null
所以要做好判断。
if(StringUtils.isNullString(refund_fee) && StringUtils.isNullString(gmt_refund)){
//支付时回调,直接将之前写的代码放进去
}else if(!StringUtils.isNullString(refund_fee) && !StringUtils.isNullString(gmt_refund)){
//全额退款时回调,
return "success";
}else{
LogComm.setLog("未知的支付宝回调功能!");
return "fail";
}
这样支付宝退款功能就ok了。至于微信,还没有去看, 是否跟支付宝一样,如果是的话,我估计微信有点坑。
以上功能是咨询了支付宝技术客服,然后自己写了。并且已测试通过。