| @@ -118,4 +118,11 @@ public interface TtMaService { | |||||
| */ | */ | ||||
| TtMaUserService getUserService(); | TtMaUserService getUserService(); | ||||
| /** | |||||
| * 返回用户相关接口方法的实现类对象,以方便调用其各个接口. | |||||
| * | |||||
| * @return TtMaUserService | |||||
| */ | |||||
| TtMaQrcodeService getQrcodeService(); | |||||
| } | } | ||||
| @@ -7,6 +7,8 @@ import cn.binarywang.wx.miniapp.config.WxMaConfig; | |||||
| import com.google.common.base.Joiner; | import com.google.common.base.Joiner; | ||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||
| import com.google.gson.JsonParser; | import com.google.gson.JsonParser; | ||||
| import com.iformall.douyin.miniapp.api.TtMaQrcode; | |||||
| import com.iformall.douyin.miniapp.api.TtMaQrcodeService; | |||||
| import com.iformall.douyin.miniapp.api.TtMaService; | import com.iformall.douyin.miniapp.api.TtMaService; | ||||
| import com.iformall.douyin.miniapp.api.TtMaUserService; | import com.iformall.douyin.miniapp.api.TtMaUserService; | ||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| @@ -45,6 +47,7 @@ public class TtMaServiceImpl implements TtMaService, RequestHttp<CloseableHttpCl | |||||
| private WxMaConfig wxMaConfig; | private WxMaConfig wxMaConfig; | ||||
| private TtMaUserService userService = new TtMaUserServiceImpl(this); | private TtMaUserService userService = new TtMaUserServiceImpl(this); | ||||
| private TtMaQrcodeService qrcodeService = new TtMaQrcodeServiceImpl(this); | |||||
| private int retrySleepMillis = 1000; | private int retrySleepMillis = 1000; | ||||
| private int maxRetryTimes = 5; | private int maxRetryTimes = 5; | ||||
| @@ -271,4 +274,9 @@ public class TtMaServiceImpl implements TtMaService, RequestHttp<CloseableHttpCl | |||||
| return this.userService; | return this.userService; | ||||
| } | } | ||||
| @Override | |||||
| public TtMaQrcodeService getQrcodeService() { | |||||
| return this.qrcodeService; | |||||
| } | |||||
| } | } | ||||
| @@ -1,26 +1,26 @@ | |||||
| package com.iformall.douyin.pay; | package com.iformall.douyin.pay; | ||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.net.URLEncoder; | |||||
| import java.nio.charset.Charset; | |||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
| import java.security.MessageDigest; | import java.security.MessageDigest; | ||||
| import java.security.NoSuchAlgorithmException; | import java.security.NoSuchAlgorithmException; | ||||
| import java.util.*; | import java.util.*; | ||||
| import java.util.Map.Entry; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.douyin.pay.enums.AppAddSubMerchantUrlType; | |||||
| import com.iformall.douyin.pay.orderQuery.QueryMerchantResult; | |||||
| import com.iformall.douyin.pay.orderQuery.QuerySettleResult; | |||||
| import com.iformall.douyin.pay.preOrder.*; | |||||
| import com.iformall.enums.EnumPayStatus; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.utils.sign.SignUtils; | import com.iformall.utils.sign.SignUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import com.alibaba.fastjson.JSON; | import com.alibaba.fastjson.JSON; | ||||
| import com.alibaba.fastjson.JSONObject; | import com.alibaba.fastjson.JSONObject; | ||||
| import com.iformall.douyin.pay.orderQuery.OrderQueryResult; | import com.iformall.douyin.pay.orderQuery.OrderQueryResult; | ||||
| import com.iformall.douyin.pay.preOrder.CreatePreOrderResult; | |||||
| import com.iformall.douyin.pay.preOrder.DouYinCreatePreOrder; | |||||
| import com.iformall.utils.HashUtil; | |||||
| import com.iformall.utils.HttpUtil; | import com.iformall.utils.HttpUtil; | ||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import springfox.documentation.spring.web.json.Json; | |||||
| /** | /** | ||||
| * 抖音小程序支付 | * 抖音小程序支付 | ||||
| @@ -122,7 +122,9 @@ public class DouYinPayHelper { | |||||
| //服务端预下单 | //服务端预下单 | ||||
| public static CreatePreOrderResult createPreOrder(DouYinCreatePreOrder preOrder) { | public static CreatePreOrderResult createPreOrder(DouYinCreatePreOrder preOrder) { | ||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/create_order", preOrder.toRequestMap()); | |||||
| Map map = preOrder.toRequestMap(); | |||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/create_order", map); | |||||
| log.info("服务端预下单 request:"+map.toString()+" response:"+response); | |||||
| JSONObject jsonObject = JSON.parseObject(response); | JSONObject jsonObject = JSON.parseObject(response); | ||||
| Integer code = jsonObject.getInteger("err_no"); | Integer code = jsonObject.getInteger("err_no"); | ||||
| if (null != code && code.intValue() == 0 ) { | if (null != code && code.intValue() == 0 ) { | ||||
| @@ -156,11 +158,13 @@ public class DouYinPayHelper { | |||||
| map.put("out_order_no",orderNo); | map.put("out_order_no",orderNo); | ||||
| // map.put("sign",createSign(map, secrect)); | // map.put("sign",createSign(map, secrect)); | ||||
| map.put("sign",getSign(map)); | map.put("sign",getSign(map)); | ||||
| map.remove("salt"); | |||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/query_order", map); | String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/query_order", map); | ||||
| log.info("查询订单结果 response:"+response); | |||||
| log.info("查询订单结果 request:"+map.toString()+" response:"+response); | |||||
| JSONObject jsonObject = JSON.parseObject(response); | JSONObject jsonObject = JSON.parseObject(response); | ||||
| JSONObject info = jsonObject.getJSONObject("payment_info"); | |||||
| if (null != info) { | |||||
| Integer code = jsonObject.getInteger("err_no"); | |||||
| if (null != code && code.intValue() == 0 ) { | |||||
| JSONObject info = jsonObject.getJSONObject("payment_info"); | |||||
| OrderQueryResult result = new OrderQueryResult(); | OrderQueryResult result = new OrderQueryResult(); | ||||
| result.setChannelGatewayNo(info.getString("channel_gateway_no")); | result.setChannelGatewayNo(info.getString("channel_gateway_no")); | ||||
| result.setChannelNo(info.getString("channel_no")); | result.setChannelNo(info.getString("channel_no")); | ||||
| @@ -170,8 +174,180 @@ public class DouYinPayHelper { | |||||
| result.setTotalFee(info.getInteger("total_fee")); | result.setTotalFee(info.getInteger("total_fee")); | ||||
| return result; | return result; | ||||
| }else { | }else { | ||||
| log.error("orderQuery reponse error. request: "+JSON.toJSONString(map)+" response:"+response); | |||||
| log.info("orderQuery reponse error. request: "+JSON.toJSONString(map)+" response:"+response); | |||||
| String errTips = jsonObject.getString("err_tips"); | |||||
| if(code != null && code.intValue() == 2000 && "单号记录不存在".equals(errTips)){ | |||||
| return null; | |||||
| }else if(code != null && code.intValue() == 3100 && "未找到相应支付单".equals(errTips)){ | |||||
| return null; | |||||
| }else{ | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "订单查询状态非法异常"); | |||||
| } | |||||
| } | |||||
| } | |||||
| public static int getPayStatusFromOrderQueryResult(OrderQueryResult result,String payOrderNo) { | |||||
| if(result == null){ | |||||
| return EnumPayStatus.PAY_STATUS_ORDER_NOT_EXISTS.getCode(); | |||||
| } | |||||
| String orderStatus = result.getOrderStatus(); | |||||
| if("PROCESSING".equals(orderStatus)){ | |||||
| return EnumPayStatus.PAY_STATUS_WAIT.getCode(); | |||||
| }else if("SUCCESS".equals(orderStatus)){ | |||||
| return EnumPayStatus.PAY_STATUS_SUCCESS.getCode(); | |||||
| }else if("FAIL".equals(orderStatus)){ | |||||
| return EnumPayStatus.PAY_STATUS_FAIL.getCode(); | |||||
| }else if("TIMEOUT".equals(orderStatus)){ | |||||
| return EnumPayStatus.PAY_STATUS_FAIL.getCode(); | |||||
| } | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "订单查询抖音支付状态失败"+payOrderNo); | |||||
| } | |||||
| //小程序开发者为分账方进件 | |||||
| //POST https://developer.toutiao.com/api/apps/ecpay/saas/app_add_sub_merchant | |||||
| public static AppAddSubMerchantResult appAddSubMerchant(AppAddSubMerchant appAddSubMerchant) { | |||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/saas/app_add_sub_merchant", appAddSubMerchant.toRequestMap()); | |||||
| JSONObject jsonObject = JSON.parseObject(response); | |||||
| Integer code = jsonObject.getInteger("err_no"); | |||||
| if (null != code && code.intValue() == 0 ) { | |||||
| AppAddSubMerchantResult result = new AppAddSubMerchantResult(); | |||||
| result.setSuccess(true); | |||||
| result.setUrl(jsonObject.getString("url")); | |||||
| result.setMerchantId(jsonObject.getString("merchant_id")); | |||||
| return result; | |||||
| }else { | |||||
| log.error("appAddSubMerchant reponse error. request: "+JSON.toJSONString(appAddSubMerchant.toRequestMap())+" response:"+response); | |||||
| AppAddSubMerchantResult result = new AppAddSubMerchantResult(); | |||||
| result.setSuccess(false); | |||||
| result.setMsg(jsonObject.getString("err_tips")); | |||||
| return result; | |||||
| } | |||||
| } | |||||
| //查询进件 | |||||
| //POST https://developer.toutiao.com/api/apps/ecpay/saas/query_merchant_status | |||||
| public static QueryMerchantResult queryMerchantStatus(String appId, String salt, String merchantId, String subMerchantId, String thirdParytyId) { | |||||
| Map map = new HashMap(); | |||||
| map.put("app_id",appId); | |||||
| map.put("salt",salt); | |||||
| map.put("merchant_id",merchantId); | |||||
| map.put("sub_merchant_id",subMerchantId); | |||||
| map.put("sign",getSign(map)); | |||||
| map.remove("salt"); | |||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/saas/query_merchant_status", map); | |||||
| log.info("查询进件结果 request:"+map.toString()+" response:"+response); | |||||
| JSONObject jsonObject = JSON.parseObject(response); | |||||
| Integer code = jsonObject.getInteger("err_no"); | |||||
| if (null != code && code.intValue() == 0 ) { | |||||
| QueryMerchantResult result = new QueryMerchantResult(); | |||||
| result.setWx(jsonObject.getInteger("wx")); | |||||
| result.setAlipay(jsonObject.getInteger("alipay")); | |||||
| return result; | |||||
| }else { | |||||
| log.error("queryMerchantStatus reponse error. request: "+JSON.toJSONString(map)+" response:"+response); | |||||
| return null; | return null; | ||||
| } | } | ||||
| } | } | ||||
| //结算与分账 | |||||
| // POST https://developer.toutiao.com/api/apps/ecpay/v1/settle | |||||
| public static SettleResult settle(Settle settle) { | |||||
| Map map = settle.toRequestMap(); | |||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/settle", map); | |||||
| log.info("分账请求 request:"+map.toString()+" response:"+response); | |||||
| JSONObject jsonObject = JSON.parseObject(response); | |||||
| Integer code = jsonObject.getInteger("err_no"); | |||||
| if (null != code && code.intValue() == 0 ) { | |||||
| SettleResult result = new SettleResult(); | |||||
| result.setSuccess(true); | |||||
| result.setSettleNo(jsonObject.getString("settle_no")); | |||||
| return result; | |||||
| }else { | |||||
| log.error("appAddSubMerchant reponse error. request: "+JSON.toJSONString(settle.toRequestMap())+" response:"+response); | |||||
| SettleResult result = new SettleResult(); | |||||
| result.setSuccess(false); | |||||
| result.setMsg(jsonObject.getString("err_tips")); | |||||
| return result; | |||||
| } | |||||
| } | |||||
| //查询分账 | |||||
| //POST https://developer.toutiao.com/api/apps/ecpay/v1/query_settle | |||||
| public static QuerySettleResult settleQuery(String appId,String salt,String settleNo,String thirdParytyId) { | |||||
| Map map = new HashMap(); | |||||
| map.put("app_id",appId); | |||||
| map.put("salt",salt); | |||||
| map.put("out_settle_no",settleNo); | |||||
| map.put("sign",getSign(map)); | |||||
| map.remove("salt"); | |||||
| String response = doPost("https://developer.toutiao.com/api/apps/ecpay/v1/query_settle", map); | |||||
| log.info("查询分账结果 request:"+map.toString()+" response:"+response); | |||||
| JSONObject jsonObject = JSON.parseObject(response); | |||||
| Integer code = jsonObject.getInteger("err_no"); | |||||
| if (null != code && code.intValue() == 0 ) { | |||||
| JSONObject info = jsonObject.getJSONObject("settle_info"); | |||||
| QuerySettleResult result = new QuerySettleResult(); | |||||
| result.setSettleNo(info.getString("settle_no")); | |||||
| result.setSettleAmount(info.getInteger("settle_amount")); | |||||
| result.setSettleStatus(info.getString("settle_status")); | |||||
| result.setMsg(jsonObject.getString("err_tips")); | |||||
| return result; | |||||
| }else { | |||||
| log.error("settleQuery reponse error. request: "+JSON.toJSONString(map)+" response:"+response); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| //测试 | |||||
| // String mcuid = "69638509385870236530";//商户号 | |||||
| // String appid = "tt9da4eb19029c2bb301"; | |||||
| // String salt = "41dcZnKe0RovCfuVEL7IlXFfy206HPVtWJ5q7KJr";//支付密钥 | |||||
| //生产 | |||||
| String mcuid = "69739487619282066230"; | |||||
| String appid = "tt8183f73e1ebb053701"; | |||||
| String salt = "rtQwyvhZHMuMYrY6GBm8DnhvEu0fuJUVHYS2KP6P"; | |||||
| // AppAddSubMerchant appAddSubMerchant = new AppAddSubMerchant(); | |||||
| // appAddSubMerchant.setAppId("tt9da4eb19029c2bb301"); | |||||
| // appAddSubMerchant.setSalt("41dcZnKe0RovCfuVEL7IlXFfy206HPVtWJ5q7KJr"); | |||||
| // appAddSubMerchant.setSubMerchantId("113"); | |||||
| // appAddSubMerchant.setUrlType(2); | |||||
| // AppAddSubMerchantResult appAddSubMerchantResult = appAddSubMerchant(appAddSubMerchant); | |||||
| // System.out.println(appAddSubMerchantResult.toString()); | |||||
| // Settle settle = new Settle(); | |||||
| // settle.setAppId(appid); | |||||
| // settle.setSalt(salt); | |||||
| ///** | |||||
| // * {"settle_params":"[{\"amount\":19,\"merchant_uid\":\"69798058370993871733\"}]", | |||||
| // * "settle_desc":"客户提现。", | |||||
| // * "sign":"94fa5f559880870f2fda53c67b236a3f", | |||||
| // * "out_settle_no":"572578660822212608", | |||||
| // * "out_order_no":"572308600038809600", | |||||
| // * "app_id":"tt9da4eb19029c2bb301"} | |||||
| // */ | |||||
| // settle.setOutSettleNo("57257866081118888"); | |||||
| // settle.setOutOrderNo("613967802405908480"); | |||||
| // settle.setSettleDesc("手动处理。"); | |||||
| // List list = new ArrayList<>(); | |||||
| // Map<String,Object> settleParams = new HashMap<>(); | |||||
| // settleParams.put("merchant_uid",mcuid); | |||||
| // settleParams.put("amount",5); | |||||
| // list.add(settleParams); | |||||
| // settle.setSettleParams(JSON.toJSONString(list)); | |||||
| // SettleResult settle1 = settle(settle); | |||||
| // System.out.println(settle1.toString()); | |||||
| // QuerySettleResult querySettleResult = settleQuery(appid, salt, "57257866081118888", null); | |||||
| // System.out.println(querySettleResult.toString()); | |||||
| // OrderQueryResult orderQueryResult = orderQuery(appid, salt, "613879951804915712", null); | |||||
| // System.out.println(orderQueryResult.toString()); | |||||
| QueryMerchantResult queryMerchantResult = queryMerchantStatus(appid, salt, "69845881593843571583", "5041", null); | |||||
| System.out.println(queryMerchantResult.toString()); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,37 @@ | |||||
| package com.iformall.douyin.pay.enums; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum AppAddSubMerchantUrlType { | |||||
| improt_URL(1, "进件页面"), | |||||
| Balance_URL(2, "余额页面"), | |||||
| ; | |||||
| public static AppAddSubMerchantUrlType getEnum(Integer code) { | |||||
| for (AppAddSubMerchantUrlType value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| AppAddSubMerchantUrlType(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,10 @@ | |||||
| package com.iformall.douyin.pay.orderQuery; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class QueryMerchantResult { | |||||
| private Integer wx;//微信渠道进件状态,0-未进件、1-进件成功、2-进件失败、3-审核中、4-冻结中 | |||||
| private Integer alipay;//支付宝渠道进件状态,0-未进件、1-进件成功、2-进件失败、3-审核中 | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| package com.iformall.douyin.pay.orderQuery; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class QuerySettleResult { | |||||
| private String settleNo;//担保支付侧的分账单号 | |||||
| private Integer settleAmount;//分账金额,单位[分] | |||||
| private String settleStatus;//分账状态,成功-SUCCESS;失败-FAIL | |||||
| private String msg; | |||||
| } | |||||
| @@ -0,0 +1,28 @@ | |||||
| package com.iformall.douyin.pay.preOrder; | |||||
| import com.iformall.douyin.pay.DouYinPayHelper; | |||||
| import lombok.Data; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| @Data | |||||
| public class AppAddSubMerchant { | |||||
| private String appId;//小程序 AppID | |||||
| private String salt;// | |||||
| private String subMerchantId;//商户 id,用于接入方自行标识并管理进件方。由开发者自行分配管理 | |||||
| private Integer urlType;//链接类型:1-进件页面 2-账户余额页 | |||||
| public Map toRequestMap() { | |||||
| Map map = new HashMap(); | |||||
| map.put("app_id", appId); | |||||
| map.put("salt",salt); | |||||
| map.put("sub_merchant_id",subMerchantId); | |||||
| map.put("url_type", urlType); | |||||
| map.put("sign", DouYinPayHelper.getSign(map)); | |||||
| map.remove("salt"); | |||||
| return map; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,13 @@ | |||||
| package com.iformall.douyin.pay.preOrder; | |||||
| import lombok.Data; | |||||
| @Data | |||||
| public class AppAddSubMerchantResult { | |||||
| private boolean success; | |||||
| private String msg; | |||||
| private String url; | |||||
| private String merchantId; | |||||
| } | |||||
| @@ -9,4 +9,5 @@ public class CreatePreOrderResult { | |||||
| private String msg; | private String msg; | ||||
| private String orderId; | private String orderId; | ||||
| private String token; | private String token; | ||||
| } | } | ||||
| @@ -55,6 +55,7 @@ public class DouYinCreatePreOrder { | |||||
| } | } | ||||
| map.put("sign", DouYinPayHelper.getSign(map)); | map.put("sign", DouYinPayHelper.getSign(map)); | ||||
| map.remove("salt"); | |||||
| return map; | return map; | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,54 @@ | |||||
| package com.iformall.douyin.pay.preOrder; | |||||
| import com.iformall.douyin.pay.DouYinPayHelper; | |||||
| import lombok.Data; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| @Data | |||||
| public class Settle { | |||||
| private String appId;//小程序 AppID | |||||
| private String salt;// | |||||
| private String thirdpartyId;//第三方平台服务商 id ,非服务商模式留空【非必填】 | |||||
| private String outSettleNo;//开发者侧的结算号, 不可重复 | |||||
| private String outOrderNo;//商户分配订单号,标识进行结算的订单 | |||||
| private String settleDesc;//结算描述,长度限制 80 个字符 | |||||
| private String notifyUrl;//商户自定义回调地址【非必填】 | |||||
| /** | |||||
| * { | |||||
| * "merchant_uid": "分账方商户号", | |||||
| * "amount": "分账金额" | |||||
| * } | |||||
| */ | |||||
| private String settleParams;//其他分账方信息,分账分配参数 SettleParameter 数组序列化后生成的 json 格式字符串【非必填】 | |||||
| private String cpExtra;//开发者自定义字段,回调原样回传【非必填】 | |||||
| public Map toRequestMap() { | |||||
| Map map = new HashMap(); | |||||
| map.put("app_id", appId); | |||||
| map.put("salt",salt); | |||||
| map.put("out_settle_no",outSettleNo); | |||||
| map.put("out_order_no",outOrderNo); | |||||
| map.put("settle_desc",settleDesc); | |||||
| if(StringUtils.isNotBlank(settleParams)){ | |||||
| map.put("settle_params",settleParams); | |||||
| } | |||||
| if(StringUtils.isNotBlank(cpExtra)){ | |||||
| map.put("cp_extra", cpExtra); | |||||
| } | |||||
| if(StringUtils.isNotBlank(notifyUrl)){ | |||||
| map.put("notify_url", notifyUrl); | |||||
| } | |||||
| if(StringUtils.isNotBlank(thirdpartyId)){ | |||||
| map.put("thirdparty_id", thirdpartyId); | |||||
| } | |||||
| map.put("sign", DouYinPayHelper.getSign(map)); | |||||
| map.remove("salt"); | |||||
| return map; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| package com.iformall.douyin.pay.preOrder; | |||||
| import com.iformall.douyin.pay.DouYinPayHelper; | |||||
| import lombok.Data; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| @Data | |||||
| public class SettleResult { | |||||
| private boolean success; | |||||
| private String msg; | |||||
| private String settleNo;//平台生成分账单号 | |||||
| } | |||||
| @@ -1,248 +1,63 @@ | |||||
| package com.iformall.service.pay.service.pay.douyin; | package com.iformall.service.pay.service.pay.douyin; | ||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.WxAppinfo; | import com.iformall.domain.po.WxAppinfo; | ||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.enums.EnumPayMode; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayOrderQ; | |||||
| import com.iformall.pay.WxPayOrderSQ; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.service.helper.WxPayOrderServiceHelper; | |||||
| import com.iformall.douyin.miniapp.api.TtMaService; | |||||
| import com.iformall.douyin.pay.DouYinPayHelper; | |||||
| import com.iformall.douyin.pay.orderQuery.OrderQueryResult; | |||||
| import com.iformall.enums.EnumPayStatus; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | ||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | ||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.MaUtil; | import com.iformall.utils.MaUtil; | ||||
| import com.iformall.utils.QRCodeUtils; | import com.iformall.utils.QRCodeUtils; | ||||
| import com.iformall.utils.Utility; | |||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.open.api.WxOpenService; | |||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Map; | |||||
| @Slf4j | @Slf4j | ||||
| public class BaseTtPayAdapterService { | public class BaseTtPayAdapterService { | ||||
| protected PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | protected PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | ||||
| throws Exception { | throws Exception { | ||||
| Map<String, String> retMap = WxPayOrderServiceHelper.wxOrderPayStatusMap(oldRecord, appInfo, payAccount); | |||||
| int code = WxPayOrderServiceHelper.getPayStatusFromMap(retMap,oldRecord.getPayOrderNo()); | |||||
| String msg = WxPayOrderServiceHelper.getPayStatusMsg(retMap, oldRecord.getPayOrderNo()); | |||||
| PayQueryAdapterResult result = new PayQueryAdapterResult(code, msg, retMap,retMap.get("transaction_id"),retMap.get("time_end")); | |||||
| OrderQueryResult orderQueryResult = DouYinPayHelper.orderQuery(appInfo.getAppId(), payAccount.getApiKey(), oldRecord.getPayOrderNo(), null); | |||||
| int code = DouYinPayHelper.getPayStatusFromOrderQueryResult(orderQueryResult,oldRecord.getPayOrderNo()); | |||||
| PayQueryAdapterResult result = new PayQueryAdapterResult(code, EnumPayStatus.getEnum(code).getMessage(), orderQueryResult,oldRecord.getPayOrderNo(),orderQueryResult.getPayTime()); | |||||
| return result; | return result; | ||||
| } | } | ||||
| protected int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception { | protected int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception { | ||||
| return WxPayOrderServiceHelper.getPayStatusFromMap((Map<String, String>) statusObject.getData(),orderOutNo); | |||||
| return statusObject.getCode(); | |||||
| } | } | ||||
| protected int queryPayStatusCode(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | protected int queryPayStatusCode(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | ||||
| throws Exception { | throws Exception { | ||||
| return WxPayOrderServiceHelper.wxOrderPayStatus(oldRecord, appInfo, payAccount); | |||||
| return queryPayStatus(oldRecord,appInfo,payAccount).getCode(); | |||||
| } | } | ||||
| JSONObject errorMapClose = JSON.parseObject("{" + | |||||
| "\"ORDERPAID\":{\"detail\":\"订单已支付\",\"reason\":\"订单已支付,不能发起关单\",\"resolution\":\"订单已支付,不能发起关单,请当作已支付的正常交易\"}," + | |||||
| "\"SYSTEMERROR\":{\"detail\":\"系统错误\",\"reason\":\"系统错误\",\"resolution\":\"系统异常,请重新调用该API\"}," + | |||||
| "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"订单已关闭,无法重复关闭\",\"resolution\":\"订单已关闭,无需继续调用\"}," + | |||||
| "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + | |||||
| "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + | |||||
| "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"reason\":\"请检查XML参数格式是否正确\"}}"); | |||||
| protected PayAdapterResult closeOrder(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) { | protected PayAdapterResult closeOrder(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) { | ||||
| String response = closeOrderWx(appInfo, record,payAccount); | |||||
| log.info("pay order close, " + record.toString() + ", response: " + response); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String return_code = returnMap.get("return_code"); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equalsIgnoreCase(return_code)) { | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| return new PayAdapterResult(true, "success", returnMap, null); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMapClose.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } else { | |||||
| String errMsg = returnMap.get("return_msg"); | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| return new PayAdapterResult(true, "success", null, null); | |||||
| } | } | ||||
| private String closeOrderWx(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) { | |||||
| // get payAccount | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| // 普通商户号模式 | |||||
| WxPayOrderQ payOrderC = new WxPayOrderQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderC.setAppid(appInfo.getAppId()); | |||||
| payOrderC.setMch_id(payAccount.getMchId()); | |||||
| payOrderC.setNonce_str(noncestr); | |||||
| payOrderC.setOut_trade_no(record.getPayOrderNo()); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderC); | |||||
| payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderC); | |||||
| String response = WxPay.closeOrder(map); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| // 服务商模式 | |||||
| WxPayOrderSQ payOrderSC = new WxPayOrderSQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderSC.setAppid(appInfo.getParentAppId()); | |||||
| payOrderSC.setSub_appid(appInfo.getAppId()); | |||||
| payOrderSC.setMch_id(payAccount.getMchId()); | |||||
| payOrderSC.setSub_mch_id(payAccount.getSubMchId()); | |||||
| payOrderSC.setNonce_str(noncestr); | |||||
| payOrderSC.setOut_trade_no(record.getPayOrderNo()); | |||||
| payOrderSC.setSign_type("HMAC-SHA256"); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderSC); | |||||
| payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderSC); | |||||
| String response = WxPay.closeOrder(map); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| } | |||||
| protected PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) throws Exception { | protected PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) throws Exception { | ||||
| String response = payOrderReverseWx(appInfo, record,payAccount); | |||||
| log.info("pay order reverse, " + record.toString() + ", response: " + response); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String return_code = returnMap.get("return_code"); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equalsIgnoreCase(return_code)) { | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| return new PayAdapterResult(true, "订单撤销成功", returnMap, null); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMapClose.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } else { | |||||
| String errMsg = returnMap.get("return_msg"); | |||||
| return new PayAdapterResult(false, errMsg, returnMap, null); | |||||
| } | |||||
| } | |||||
| private String payOrderReverseWx(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) { | |||||
| // get payAccount | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| // 普通商户号模式 | |||||
| WxPayOrderQ payOrderC = new WxPayOrderQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderC.setAppid(appInfo.getAppId()); | |||||
| payOrderC.setMch_id(payAccount.getMchId()); | |||||
| payOrderC.setNonce_str(noncestr); | |||||
| payOrderC.setOut_trade_no(record.getPayOrderNo()); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderC); | |||||
| payOrderC.setSign(WxPayment.createSign(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderC); | |||||
| String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| // 服务商模式 | |||||
| WxPayOrderSQ payOrderSC = new WxPayOrderSQ(); | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| payOrderSC.setAppid(appInfo.getParentAppId()); | |||||
| payOrderSC.setSub_appid(appInfo.getAppId()); | |||||
| payOrderSC.setMch_id(payAccount.getMchId()); | |||||
| payOrderSC.setSub_mch_id(payAccount.getSubMchId()); | |||||
| payOrderSC.setNonce_str(noncestr); | |||||
| payOrderSC.setOut_trade_no(record.getPayOrderNo()); | |||||
| payOrderSC.setSign_type("HMAC-SHA256"); | |||||
| try { | |||||
| Map map = BeanUtils.toStringMap(payOrderSC); | |||||
| payOrderSC.setSign(WxPayment.createSignHMAC(map, payAccount.getApiKey())); | |||||
| map = BeanUtils.toStringMap(payOrderSC); | |||||
| String response = WxPay.orderReverse(map, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| log.info("request:" + map.toString() + "\nresponse:" + response); | |||||
| return response; | |||||
| } catch (RuntimeException e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| return new PayAdapterResult(true, "订单撤销成功", null, null); | |||||
| } | } | ||||
| @Autowired | |||||
| WxOpenService openService; | |||||
| @Autowired | @Autowired | ||||
| MaUtil maUtil; | MaUtil maUtil; | ||||
| protected File getQrCode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam) throws WxErrorException { | protected File getQrCode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam) throws WxErrorException { | ||||
| boolean isFmOpen = false; | |||||
| WxMaService wxMaService; | |||||
| if(isFmOpen) { | |||||
| wxMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appinfo.getAppId()); | |||||
| } else { | |||||
| wxMaService = maUtil.getWeappService(appinfo); | |||||
| } | |||||
| boolean autoColor = false; | |||||
| boolean isHyaline = true; | |||||
| WxMaCodeLineColor color = new WxMaCodeLineColor("0", "0", "0"); | |||||
| TtMaService ttappService = maUtil.getTtappService(appinfo); | |||||
| String pathStr = ""; | String pathStr = ""; | ||||
| if (StringUtils.isNotBlank(sceneParam)) { | if (StringUtils.isNotBlank(sceneParam)) { | ||||
| pathStr = pageUrl + "?scene="+sceneParam; | pathStr = pageUrl + "?scene="+sceneParam; | ||||
| } else { | } else { | ||||
| pathStr = pageUrl; | pathStr = pageUrl; | ||||
| } | } | ||||
| if(type == 0) { | |||||
| final File codeFile = wxMaService.getQrcodeService().createQrcode(pathStr, QRCodeUtils.QR_WIDTH); | |||||
| return codeFile; | |||||
| }else { | |||||
| final File codeFile = wxMaService.getQrcodeService().createWxaCodeUnlimit(sceneParam, pageUrl, QRCodeUtils.QR_WIDTH, autoColor, color, isHyaline); | |||||
| return codeFile; | |||||
| } | |||||
| final File codeFile = ttappService.getQrcodeService().createTtaCode("douyin", pathStr, QRCodeUtils.QR_WIDTH); | |||||
| return codeFile; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,237 +1,60 @@ | |||||
| package com.iformall.service.pay.service.pay.douyin.miniApp; | package com.iformall.service.pay.service.pay.douyin.miniApp; | ||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.WxAppinfo; | import com.iformall.domain.po.WxAppinfo; | ||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.enums.EnumPayMode; | |||||
| import com.iformall.douyin.pay.DouYinPayHelper; | |||||
| import com.iformall.douyin.pay.preOrder.CreatePreOrderResult; | |||||
| import com.iformall.douyin.pay.preOrder.DouYinCreatePreOrder; | |||||
| import com.iformall.enums.EnumPayShare; | import com.iformall.enums.EnumPayShare; | ||||
| import com.iformall.enums.EnumPayStatus; | import com.iformall.enums.EnumPayStatus; | ||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayOrderP; | |||||
| import com.iformall.pay.WxPayOrderSP; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.service.order.entity.WxComposeOrder; | import com.iformall.service.order.entity.WxComposeOrder; | ||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | import com.iformall.service.pay.service.pay.CDrivingPayService; | ||||
| import com.iformall.service.pay.service.pay.douyin.BaseTtPayAdapterService; | import com.iformall.service.pay.service.pay.douyin.BaseTtPayAdapterService; | ||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | ||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | ||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.MapUtil; | |||||
| import com.iformall.utils.Utility; | |||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.Map; | |||||
| @Slf4j | @Slf4j | ||||
| @Service | @Service | ||||
| public class TtMiniAppPayAdapterService extends BaseTtPayAdapterService implements CDrivingPayService{ | public class TtMiniAppPayAdapterService extends BaseTtPayAdapterService implements CDrivingPayService{ | ||||
| JSONObject errorMap = JSON.parseObject("{" + | |||||
| "\"NOAUTH\":{\"detail\":\"商户无此接口权限\",\"reason\":\"商户未开通此接口权限\",\"resolution\":\"请商户前往申请此接口权限\"}," + | |||||
| "\"NOTENOUGH\":{\"detail\":\"余额不足\",\"reason\":\"用户帐号余额不足\",\"resolution\":\"用户帐号余额不足,请用户充值或更换支付卡后再支付\"}," + | |||||
| "\"ORDERPAID\":{\"detail\":\"商户订单已支付\",\"reason\":\"商户订单已支付,无需重复操作\",\"resolution\":\"商户订单已支付,无需更多操作\"}," + | |||||
| "\"ORDERCLOSED\":{\"detail\":\"订单已关闭\",\"reason\":\"当前订单已关闭,无法支付\",\"resolution\":\"当前订单已关闭,请重新下单\"}," + | |||||
| "\"SYSTEMERROR\":{\"detail\":\"系统错误\t\",\"reason\":\"系统超时\",\"resolution\":\"系统异常,请用相同参数重新调用\"}," + | |||||
| "\"APPID_NOT_EXIST\":{\"detail\":\"APPID不存在\",\"reason\":\"参数中缺少APPID\",\"resolution\":\"请检查APPID是否正确\"}," + | |||||
| "\"MCHID_NOT_EXIST\":{\"detail\":\"MCHID不存在\",\"reason\":\"参数中缺少MCHID\",\"resolution\":\"请检查MCHID是否正确\"}," + | |||||
| "\"APPID_MCHID_NOT_MATCH\":{\"detail\":\"appid和mch_id不匹配\",\"reason\":\"appid和mch_id不匹配\",\"resolution\":\"请确认appid和mch_id是否匹配\"}," + | |||||
| "\"LACK_PARAMS\":{\"detail\":\"缺少参数\t\",\"reason\":\"缺少必要的请求参数\",\"resolution\":\"请检查参数是否齐全\"}," + | |||||
| "\"OUT_TRADE_NO_USED\":{\"detail\":\"商户订单号重复\",\"reason\":\"同一笔交易不能多次提交\",\"resolution\":\"请核实商户订单号是否重复提交\"}," + | |||||
| "\"SIGNERROR\":{\"detail\":\"签名错误\",\"reason\":\"参数签名结果不正确\",\"resolution\":\"请检查签名参数和方法是否都符合签名算法要求\"}," + | |||||
| "\"XML_FORMAT_ERROR\":{\"detail\":\"XML格式错误\t\",\"reason\":\"XML格式错误\",\"resolution\":\"请检查XML参数格式是否正确\"}," + | |||||
| "\"REQUIRE_POST_METHOD\":{\"detail\":\"请使用post方法\",\"reason\":\"未使用post传递参数\",\"resolution\":\"请检查请求参数是否通过post方法提交\"}," + | |||||
| "\"POST_DATA_EMPTY\":{\"detail\":\"post数据为空\",\"reason\":\"post数据不能为空\",\"resolution\":\"请检查post数据是否为空\"}," + | |||||
| "\"NOT_UTF8\":{\"detail\":\"编码格式错误\",\"reason\":\"未使用指定编码格式\",\"resolution\":\"请使用UTF-8编码格式\"}}"); | |||||
| private WxPayOrderP generateWxPayOrderP(WxPayAccount payAccount,WxComposeOrder composeOrder,String productName, WxPayOrder record,String openId,String appId,Date currentDate) throws Exception { | |||||
| // 统一下单 普通商户模式 | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| WxPayOrderP wxPayOrderP = new WxPayOrderP(); | |||||
| wxPayOrderP.setOpenid(openId); | |||||
| wxPayOrderP.setAppid(appId); | |||||
| wxPayOrderP.setMch_id(payAccount.getMchId()); | |||||
| wxPayOrderP.setNonce_str(noncestr); | |||||
| wxPayOrderP.setBody(productName); | |||||
| wxPayOrderP.setOut_trade_no(record.getPayOrderNo()); | |||||
| wxPayOrderP.setTotal_fee(composeOrder.getPayment()); | |||||
| wxPayOrderP.setSpbill_create_ip(record.getIp()); // 终端IP | |||||
| wxPayOrderP.setGoods_tag(productName); | |||||
| wxPayOrderP.setNotify_url(payAccount.getPayNotifyUrl()); | |||||
| wxPayOrderP.setTrade_type(WxPay.TradeType.JSAPI.name()); // 终端类型 | |||||
| wxPayOrderP.setProduct_id(String.valueOf(composeOrder.getMainOrderId())); // 订单ID | |||||
| wxPayOrderP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); | |||||
| Date futureDate = new Date(); | |||||
| futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); | |||||
| wxPayOrderP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 | |||||
| Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderP); | |||||
| wxPayOrderP.setSign(WxPayment.createSign(payOrderMap, payAccount.getApiKey())); | |||||
| return wxPayOrderP; | |||||
| } | |||||
| private PayAdapterResult getOrderPResult(Map<String, String> returnMap,WxPayOrder record,WxPayAccount payAccount,String noncestr) { | |||||
| PayAdapterResult par = new PayAdapterResult(); | |||||
| returnMap.put("payOrderId", String.valueOf(record.getId())); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| par.setSuccess(true); | |||||
| par.setMsg("success."); | |||||
| par.setData(returnMap); | |||||
| String prepay_id = returnMap.get("prepay_id"); | |||||
| // update payOrder with prepay_id | |||||
| record.setPrepayId(prepay_id); | |||||
| record.setUpdateTime(new Date()); | |||||
| record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); | |||||
| @Override | |||||
| public PayAdapterResult pay(WxPayAccount payAccount, WxPayOrder record,WxComposeOrder composeOrder,String productName,EnumPayShare isShare,WxAppinfo appInfo,Date currentDate, PayExtraParam params) throws Exception { | |||||
| DouYinCreatePreOrder preOrder = new DouYinCreatePreOrder(); | |||||
| preOrder.setAppId(appInfo.getAppId()); | |||||
| preOrder.setSercrect(appInfo.getSecret()); | |||||
| preOrder.setSalt(payAccount.getApiKey()); | |||||
| preOrder.setOutOrderNo(record.getPayOrderNo()); | |||||
| preOrder.setTotalAmount(composeOrder.getPayment()); | |||||
| preOrder.setSubject(productName); | |||||
| preOrder.setBody(productName); | |||||
| preOrder.setValidTime(15*60); | |||||
| // preOrder.setNotifyUrl();//回调地址 | |||||
| // preOrder.setThirdpartyId();//第三方服务商ID | |||||
| // preOrder.setStoreUid(order.getStoreUid()); | |||||
| CreatePreOrderResult preOrderResult = DouYinPayHelper.createPreOrder(preOrder); | |||||
| String timestamp = String.valueOf(Utility.getCurrentTimeStamp()); | |||||
| Map<String, String> sighMap = MapUtil.getOrderMap(); | |||||
| sighMap.put("appId", returnMap.get("appid")); | |||||
| sighMap.put("timeStamp", timestamp); | |||||
| sighMap.put("nonceStr", noncestr); | |||||
| sighMap.put("package", "prepay_id=" + prepay_id); | |||||
| sighMap.put("signType", "MD5"); | |||||
| String signAgent = WxPayment.createSign(sighMap, payAccount.getApiKey()); | |||||
| returnMap.put("timeStamp", timestamp); | |||||
| returnMap.put("nonceStr", noncestr); | |||||
| returnMap.put("package", "prepay_id=" + prepay_id); | |||||
| returnMap.put("paySign", signAgent); | |||||
| log.info("back to UI: " + returnMap.toString()); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMap.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| record.setFailReason(errMsg); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| record.setFailReason(errMsg); | |||||
| } | |||||
| record.setUpdateTime(new Date()); | |||||
| par.setSuccess(false); | |||||
| par.setMsg(errMsg); | |||||
| par.setData(returnMap); | |||||
| } | |||||
| return par; | |||||
| } | |||||
| private WxPayOrderSP generateWxPayOrderSP(WxPayAccount payAccount, WxComposeOrder composeOrder,String productName,WxPayOrder record,WxAppinfo appInfo,String openId,String appId,Date currentDate,EnumPayShare isShare) throws Exception { | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| WxPayOrderSP wxPayOrderSP = new WxPayOrderSP(); | |||||
| wxPayOrderSP.setSub_openid(openId); | |||||
| wxPayOrderSP.setAppid(appInfo.getParentAppId()); | |||||
| wxPayOrderSP.setMch_id(payAccount.getMchId()); | |||||
| wxPayOrderSP.setSub_appid(appId); | |||||
| wxPayOrderSP.setSub_mch_id(payAccount.getSubMchId()); | |||||
| wxPayOrderSP.setNonce_str(noncestr); | |||||
| wxPayOrderSP.setBody(productName); | |||||
| wxPayOrderSP.setOut_trade_no(record.getPayOrderNo()); | |||||
| wxPayOrderSP.setTotal_fee(composeOrder.getPayment().toString()); | |||||
| wxPayOrderSP.setSpbill_create_ip(record.getIp()); // 终端IP | |||||
| wxPayOrderSP.setGoods_tag(productName); // 券ID | |||||
| wxPayOrderSP.setNotify_url(payAccount.getPayNotifyUrl()); | |||||
| wxPayOrderSP.setTrade_type(WxPay.TradeType.JSAPI.name()); // 终端类型 | |||||
| wxPayOrderSP.setProduct_id(String.valueOf(composeOrder.getMainOrderId())); // | |||||
| wxPayOrderSP.setTime_start(Utility.getDataFormatStringYYYYMMDDHHmmss(currentDate)); | |||||
| Date futureDate = new Date(); | |||||
| futureDate.setTime(currentDate.getTime() + 15 * 60 * 1000); | |||||
| wxPayOrderSP.setTime_expire(Utility.getDataFormatStringYYYYMMDDHHmmss(futureDate)); // 15分钟后结束 | |||||
| wxPayOrderSP.setSign_type("HMAC-SHA256"); | |||||
| wxPayOrderSP.setProfit_sharing(null); | |||||
| if (isShare == EnumPayShare.YES) { | |||||
| wxPayOrderSP.setProfit_sharing("Y"); | |||||
| if(preOrderResult.isSuccess()){ | |||||
| record.setPrepayId(preOrderResult.getOrderId()); | |||||
| record.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); | |||||
| }else{ | |||||
| record.setFailReason(preOrderResult.getMsg()); | |||||
| } | } | ||||
| Map<String, String> payOrderMap = BeanUtils.toStringMap(wxPayOrderSP); | |||||
| wxPayOrderSP.setSign(WxPayment.createSignHMAC(payOrderMap, payAccount.getApiKey())); | |||||
| return wxPayOrderSP; | |||||
| } | |||||
| private PayAdapterResult getOrderSPResult(Map<String, String> returnMap,WxPayOrder record,WxPayAccount payAccount,WxAppinfo appInfo,String noncestr) { | |||||
| PayAdapterResult par = new PayAdapterResult(); | |||||
| returnMap.put("payOrderId", String.valueOf(record.getId())); | |||||
| String result_code = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equals(result_code)) { | |||||
| par.setSuccess(true); | |||||
| par.setMsg("success."); | |||||
| par.setData(returnMap); | |||||
| String prepay_id = returnMap.get("prepay_id"); | |||||
| // update payOrder with prepay_id | |||||
| record.setPrepayId(prepay_id); | |||||
| record.setUpdateTime(new Date()); | |||||
| record.setUpdateTime(new Date()); | |||||
| String timestamp = String.valueOf(Utility.getCurrentTimeStamp()); | |||||
| Map<String, String> sighMap = MapUtil.getOrderMap(); | |||||
| sighMap.put("appId", appInfo.getAppId()); | |||||
| sighMap.put("timeStamp", timestamp); | |||||
| sighMap.put("nonceStr", noncestr); | |||||
| sighMap.put("package", "prepay_id=" + prepay_id); | |||||
| sighMap.put("signType", "HMAC-SHA256"); | |||||
| String signAgent = WxPayment.createSignHMAC(sighMap, payAccount.getApiKey()); | |||||
| returnMap.put("timeStamp", timestamp); | |||||
| returnMap.put("nonceStr", noncestr); | |||||
| returnMap.put("package", "prepay_id=" + prepay_id); | |||||
| returnMap.put("paySign", signAgent); | |||||
| returnMap.put("signType", "HMAC-SHA256"); | |||||
| log.info("back to UI: " + returnMap.toString()); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorMap.getJSONObject(result_code); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| record.setFailReason(errMsg); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| record.setFailReason(errMsg); | |||||
| } | |||||
| record.setUpdateTime(new Date()); | |||||
| par.setSuccess(false); | |||||
| par.setMsg(errMsg); | |||||
| par.setData(returnMap); | |||||
| } | |||||
| PayAdapterResult par = new PayAdapterResult(); | |||||
| par.setSuccess(preOrderResult.isSuccess()); | |||||
| par.setMsg(preOrderResult.getMsg()); | |||||
| par.setTransactionId(preOrderResult.getOrderId()); | |||||
| par.setData(preOrderResult); | |||||
| return par; | return par; | ||||
| } | } | ||||
| @Override | |||||
| public PayAdapterResult pay(WxPayAccount payAccount, WxPayOrder record,WxComposeOrder composeOrder,String productName,EnumPayShare isShare,WxAppinfo appInfo,Date currentDate, PayExtraParam params) throws Exception { | |||||
| if (null == params ) { | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"openId为空"); | |||||
| } | |||||
| String openId = (String) params.getValue("openId"); | |||||
| if (StringUtils.isBlank(openId) ) { | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"openId为空"); | |||||
| } | |||||
| //普通商户模式 | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| WxPayOrderP wxPayOrderP = generateWxPayOrderP(payAccount,composeOrder,productName,record,openId,appInfo.getAppId(),currentDate); | |||||
| String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderP)); | |||||
| log.info("pay order, wechat pushOrder, " + wxPayOrderP.toString() + ", response: " + response.toString()); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| return getOrderPResult(returnMap,record,payAccount,wxPayOrderP.getNonce_str()); | |||||
| } else { | |||||
| // 统一下单 // 服务商模式 | |||||
| WxPayOrderSP wxPayOrderSP = generateWxPayOrderSP(payAccount,composeOrder,productName,record,appInfo,openId,appInfo.getAppId(),currentDate,isShare); | |||||
| String response = WxPay.pushOrder(BeanUtils.toStringMap(wxPayOrderSP)); | |||||
| log.info("pay order, wechat pushOrder, " + wxPayOrderSP.toString() + ", response: " + response.toString()); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| return getOrderSPResult(returnMap,record,payAccount,appInfo,wxPayOrderSP.getNonce_str()); | |||||
| } | |||||
| } | |||||
| @Override | @Override | ||||
| public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, | public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, | ||||