| @@ -118,4 +118,11 @@ public interface TtMaService { | |||
| */ | |||
| 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.gson.Gson; | |||
| 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.TtMaUserService; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| @@ -45,6 +47,7 @@ public class TtMaServiceImpl implements TtMaService, RequestHttp<CloseableHttpCl | |||
| private WxMaConfig wxMaConfig; | |||
| private TtMaUserService userService = new TtMaUserServiceImpl(this); | |||
| private TtMaQrcodeService qrcodeService = new TtMaQrcodeServiceImpl(this); | |||
| private int retrySleepMillis = 1000; | |||
| private int maxRetryTimes = 5; | |||
| @@ -271,4 +274,9 @@ public class TtMaServiceImpl implements TtMaService, RequestHttp<CloseableHttpCl | |||
| return this.userService; | |||
| } | |||
| @Override | |||
| public TtMaQrcodeService getQrcodeService() { | |||
| return this.qrcodeService; | |||
| } | |||
| } | |||
| @@ -1,26 +1,26 @@ | |||
| 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.security.MessageDigest; | |||
| import java.security.NoSuchAlgorithmException; | |||
| 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 org.apache.commons.lang3.StringUtils; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| 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 lombok.extern.slf4j.Slf4j; | |||
| import springfox.documentation.spring.web.json.Json; | |||
| /** | |||
| * 抖音小程序支付 | |||
| @@ -122,7 +122,9 @@ public class DouYinPayHelper { | |||
| //服务端预下单 | |||
| 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); | |||
| Integer code = jsonObject.getInteger("err_no"); | |||
| if (null != code && code.intValue() == 0 ) { | |||
| @@ -156,11 +158,13 @@ public class DouYinPayHelper { | |||
| map.put("out_order_no",orderNo); | |||
| // map.put("sign",createSign(map, secrect)); | |||
| map.put("sign",getSign(map)); | |||
| map.remove("salt"); | |||
| 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 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(); | |||
| result.setChannelGatewayNo(info.getString("channel_gateway_no")); | |||
| result.setChannelNo(info.getString("channel_no")); | |||
| @@ -170,8 +174,180 @@ public class DouYinPayHelper { | |||
| result.setTotalFee(info.getInteger("total_fee")); | |||
| return result; | |||
| }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; | |||
| } | |||
| } | |||
| //结算与分账 | |||
| // 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 orderId; | |||
| private String token; | |||
| } | |||
| @@ -55,6 +55,7 @@ public class DouYinCreatePreOrder { | |||
| } | |||
| map.put("sign", DouYinPayHelper.getSign(map)); | |||
| map.remove("salt"); | |||
| 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; | |||
| 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.WxPayAccount; | |||
| 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.PayQueryAdapterResult; | |||
| import com.iformall.utils.BeanUtils; | |||
| import com.iformall.utils.MaUtil; | |||
| import com.iformall.utils.QRCodeUtils; | |||
| import com.iformall.utils.Utility; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.open.api.WxOpenService; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import java.io.File; | |||
| import java.util.Map; | |||
| @Slf4j | |||
| public class BaseTtPayAdapterService { | |||
| protected PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, WxPayAccount payAccount) | |||
| 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; | |||
| } | |||
| 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) | |||
| 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) { | |||
| 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 { | |||
| 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 | |||
| MaUtil maUtil; | |||
| 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 = ""; | |||
| if (StringUtils.isNotBlank(sceneParam)) { | |||
| pathStr = pageUrl + "?scene="+sceneParam; | |||
| } else { | |||
| 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; | |||
| 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.WxPayAccount; | |||
| 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.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.pay.entity.PayExtraParam; | |||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | |||
| 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.PayQueryAdapterResult; | |||
| import com.iformall.utils.BeanUtils; | |||
| import com.iformall.utils.MapUtil; | |||
| import com.iformall.utils.Utility; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.stereotype.Service; | |||
| import java.io.File; | |||
| import java.util.Date; | |||
| import java.util.Map; | |||
| @Slf4j | |||
| @Service | |||
| 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; | |||
| } | |||
| @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 | |||
| public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, | |||