|  |  | @@ -0,0 +1,279 @@ | 
		
	
		
			
			|  |  |  | package com.iformall.service.pay.service.pay.wx.v3.nativePay; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | import com.alibaba.fastjson.JSON; | 
		
	
		
			
			|  |  |  | import com.alibaba.fastjson.JSONArray; | 
		
	
		
			
			|  |  |  | import com.alibaba.fastjson.JSONObject; | 
		
	
		
			
			|  |  |  | import com.github.binarywang.wxpay.exception.WxPayException; | 
		
	
		
			
			|  |  |  | import com.github.binarywang.wxpay.service.WxPayService; | 
		
	
		
			
			|  |  |  | import com.iformall.common.ErrorCode; | 
		
	
		
			
			|  |  |  | import com.iformall.domain.po.*; | 
		
	
		
			
			|  |  |  | import com.iformall.enums.*; | 
		
	
		
			
			|  |  |  | import com.iformall.exception.MallinkException; | 
		
	
		
			
			|  |  |  | import com.iformall.pay.WxPayV3; | 
		
	
		
			
			|  |  |  | import com.iformall.service.helper.WxPayOrderServiceHelper; | 
		
	
		
			
			|  |  |  | 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.entity.PayAdapterResult; | 
		
	
		
			
			|  |  |  | import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | 
		
	
		
			
			|  |  |  | import com.iformall.service.pay.service.pay.wx.sft.entity.SFTPayQueryReq; | 
		
	
		
			
			|  |  |  | import com.iformall.service.pay.service.pay.wx.v3.BaseWxPayV3AdapterService; | 
		
	
		
			
			|  |  |  | import com.iformall.service.pay.service.pay.wx.v3.entity.*; | 
		
	
		
			
			|  |  |  | import com.iformall.utils.DateUtils; | 
		
	
		
			
			|  |  |  | import com.iformall.utils.MaUtil; | 
		
	
		
			
			|  |  |  | import com.iformall.utils.Utility; | 
		
	
		
			
			|  |  |  | import lombok.extern.slf4j.Slf4j; | 
		
	
		
			
			|  |  |  | import org.apache.commons.lang3.StringUtils; | 
		
	
		
			
			|  |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
		
	
		
			
			|  |  |  | import org.springframework.stereotype.Service; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | import java.io.File; | 
		
	
		
			
			|  |  |  | import java.io.UnsupportedEncodingException; | 
		
	
		
			
			|  |  |  | import java.util.*; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Slf4j | 
		
	
		
			
			|  |  |  | @Service | 
		
	
		
			
			|  |  |  | public class WxNativePayV3AdapterService extends BaseWxPayV3AdapterService implements CDrivingPayService{ | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | @Autowired | 
		
	
		
			
			|  |  |  | MaUtil maUtil; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | private V3CreatePayReq generateCreatePayRequest(ProductOrder productOrder,WxAppinfo appInfo,WxPayAccount payAccount) throws Exception { | 
		
	
		
			
			|  |  |  | V3CreatePayReq req = new V3CreatePayReq(); | 
		
	
		
			
			|  |  |  | req.setAppid(appInfo.getAppId()); | 
		
	
		
			
			|  |  |  | req.setMchid(payAccount.getSubMchId()); | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | //中文必须要这样,否则会双方签名失败 | 
		
	
		
			
			|  |  |  | req.setDescription(WxPayV3.handleChinese(appInfo.getName()+"-"+productOrder.getProductTitle())); | 
		
	
		
			
			|  |  |  | } catch (UnsupportedEncodingException e) { | 
		
	
		
			
			|  |  |  | req.setDescription("weixin miniApp product"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | req.setOut_trade_no(productOrder.getOrderNumber()); | 
		
	
		
			
			|  |  |  | req.setNotify_url(payAccount.getPayNotifyV3Url(appInfo.getProjectType())); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | V3PayAmountReq amout = new V3PayAmountReq(); | 
		
	
		
			
			|  |  |  | amout.setTotal(productOrder.getOrderPrice()); | 
		
	
		
			
			|  |  |  | req.setAmount(amout); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | V3Payer payer = new V3Payer(); | 
		
	
		
			
			|  |  |  | payer.setOpenid(productOrder.getOpenId()); | 
		
	
		
			
			|  |  |  | req.setPayer(payer); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | return req; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | private PayAdapterResult getOrderPResult(String response,WxPayService payService,WxAppinfo appInfo,WxPayAccount payAccount,String order_no) { | 
		
	
		
			
			|  |  |  | PayAdapterResult par = new PayAdapterResult(); | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(response)) { | 
		
	
		
			
			|  |  |  | par.setSuccess(false); | 
		
	
		
			
			|  |  |  | par.setMsg("pay v3 has no response."); | 
		
	
		
			
			|  |  |  | }else { | 
		
	
		
			
			|  |  |  | JSONObject result = JSON.parseObject(response); | 
		
	
		
			
			|  |  |  | String codeUrl = result.getString("code_url"); | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(codeUrl)) { | 
		
	
		
			
			|  |  |  | par.setSuccess(false); | 
		
	
		
			
			|  |  |  | par.setMsg("pay v3 has no response."); | 
		
	
		
			
			|  |  |  | }else { | 
		
	
		
			
			|  |  |  | par.setSuccess(true); | 
		
	
		
			
			|  |  |  | par.setMsg("success."); | 
		
	
		
			
			|  |  |  | par.setData(getPayRetMap(codeUrl, order_no)); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return par; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | private Map getPayRetMap(String codeUrl,String order_no) { | 
		
	
		
			
			|  |  |  | Map returnMap = new HashMap(); | 
		
	
		
			
			|  |  |  | returnMap.put("codeUrl", codeUrl); | 
		
	
		
			
			|  |  |  | returnMap.put("payOrderId", order_no); | 
		
	
		
			
			|  |  |  | return returnMap; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayAdapterResult pay(WxPayAccount payAccount,WxPayOrder record,WxComposeOrder composeOrder,List<WxOrder> childOrders, | 
		
	
		
			
			|  |  |  | String productName,EnumPayShare isShare,WxAppinfo appInfo,Date currentDate, PayExtraParam params) throws Exception { | 
		
	
		
			
			|  |  |  | return null; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayAdapterResult createPay(ProductOrder order, WxAppinfo appInfo, WxPayAccount payAccount) throws Exception { | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | WxPayService payService = maUtil.getWxPayServiceBySelfModel(appInfo, payAccount); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | V3CreatePayReq payReq = generateCreatePayRequest(order,appInfo,payAccount); | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | String response = WxPayV3.payCommonNative(payService, payReq); | 
		
	
		
			
			|  |  |  | return getOrderPResult(response,payService,appInfo,payAccount,order.getOrderNumber()); | 
		
	
		
			
			|  |  |  | }catch(WxPayException e) { | 
		
	
		
			
			|  |  |  | log.error("wexin pay v3 error",e); | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),e.getCustomErrorMsg()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | private PayQueryAdapterResult getPayCommonQueryResult(String response) { | 
		
	
		
			
			|  |  |  | JSONObject result = JSON.parseObject(response); | 
		
	
		
			
			|  |  |  | String transtionId = result.getString("transaction_id"); | 
		
	
		
			
			|  |  |  | String tradeState = result.getString("trade_state"); | 
		
	
		
			
			|  |  |  | String tradeStateDesc = result.getString("trade_state_desc"); | 
		
	
		
			
			|  |  |  | String successTime = result.getString("success_time"); | 
		
	
		
			
			|  |  |  | EnumPayStatus payStatus = WxPayOrderServiceHelper.getPayStatus(tradeState); | 
		
	
		
			
			|  |  |  | if (null == payStatus) { | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "订单查询微信支付状态非法["+tradeState+"]"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(tradeStateDesc)) { | 
		
	
		
			
			|  |  |  | tradeStateDesc = payStatus.getMessage(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | PayQueryAdapterResult qresult = new PayQueryAdapterResult(payStatus.getCode(), tradeStateDesc,null, response,transtionId,successTime); | 
		
	
		
			
			|  |  |  | return qresult; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | private PayQueryAdapterResult getPayQueryResult(String response) { | 
		
	
		
			
			|  |  |  | JSONObject result = JSON.parseObject(response); | 
		
	
		
			
			|  |  |  | String transtionId = result.getString("transaction_id"); | 
		
	
		
			
			|  |  |  | String tradeState = result.getString("trade_state"); | 
		
	
		
			
			|  |  |  | String tradeStateDesc = result.getString("trade_state_desc"); | 
		
	
		
			
			|  |  |  | String successTime = result.getString("success_time"); | 
		
	
		
			
			|  |  |  | JSONObject payer = result.getJSONObject("payer"); | 
		
	
		
			
			|  |  |  | String openid = null; | 
		
	
		
			
			|  |  |  | if(payer != null){ | 
		
	
		
			
			|  |  |  | openid = payer.getString("openid"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | EnumProductOrderStatus payStatus = WxPayOrderServiceHelper.getProductOrderStatus(tradeState); | 
		
	
		
			
			|  |  |  | if (null == payStatus) { | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.PAY_ORDER_ERROR.getCode(), "订单查询微信支付状态非法["+tradeState+"]"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(tradeStateDesc)) { | 
		
	
		
			
			|  |  |  | tradeStateDesc = payStatus.getMessage(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | PayQueryAdapterResult qresult = new PayQueryAdapterResult(); | 
		
	
		
			
			|  |  |  | qresult.setCode(payStatus.getCode()); | 
		
	
		
			
			|  |  |  | qresult.setMsg(tradeStateDesc); | 
		
	
		
			
			|  |  |  | qresult.setTransactionId(transtionId); | 
		
	
		
			
			|  |  |  | qresult.setOpenId(openid); | 
		
	
		
			
			|  |  |  | if(StringUtils.isNotBlank(successTime)){ | 
		
	
		
			
			|  |  |  | qresult.setPayTime(DateUtils.rfc3339Formatter(successTime)); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | return qresult; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxAppinfo appInfo, | 
		
	
		
			
			|  |  |  | WxPayAccount payAccount) throws Exception { | 
		
	
		
			
			|  |  |  | WxPayService payService = maUtil.getWxPayService(appInfo, payAccount); | 
		
	
		
			
			|  |  |  | V3PayQueryReq req = new V3PayQueryReq(); | 
		
	
		
			
			|  |  |  | if (!oldRecord.isMulity()) { | 
		
	
		
			
			|  |  |  | req.setSp_mchid(payAccount.getMchId()); | 
		
	
		
			
			|  |  |  | //总分 | 
		
	
		
			
			|  |  |  | if (payAccount.getMchType() == EnumPayMchType.TOTAL.getCode()) { | 
		
	
		
			
			|  |  |  | req.setSub_mchid(payAccount.getSubMchId()); | 
		
	
		
			
			|  |  |  | }else if (payAccount.getMchType() == EnumPayMchType.DIRECT.getCode()) { | 
		
	
		
			
			|  |  |  | req.setSub_mchid(oldRecord.getSingleChildOrderShare().getMerchantUid()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | req.setOut_trade_no(oldRecord.getPayOrderNo()); | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | String response = WxPayV3.payCommonQuery(payService, req); | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(response)){ | 
		
	
		
			
			|  |  |  | log.error("pay common v3 query response is null."+JSON.toJSONString(req)); | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"pay common v3 query response is null."+JSON.toJSONString(req)); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return getPayCommonQueryResult(response); | 
		
	
		
			
			|  |  |  | }catch(WxPayException e) { | 
		
	
		
			
			|  |  |  | log.error("pay common v3 query response error",e); | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),e.getCustomErrorMsg()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | }else { | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"合单查询无法处理,暂时不支持合单支付查询"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | /** | 
		
	
		
			
			|  |  |  | * 单商户模式 | 
		
	
		
			
			|  |  |  | * @param order | 
		
	
		
			
			|  |  |  | * @param appInfo | 
		
	
		
			
			|  |  |  | * @param payAccount | 
		
	
		
			
			|  |  |  | * @return | 
		
	
		
			
			|  |  |  | * @throws Exception | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayQueryAdapterResult queryPayStatus(ProductOrder order, WxAppinfo appInfo, WxPayAccount payAccount) throws Exception { | 
		
	
		
			
			|  |  |  | WxPayService payService = maUtil.getWxPayServiceBySelfModel(appInfo, payAccount); | 
		
	
		
			
			|  |  |  | V3PayQuery req = new V3PayQuery(); | 
		
	
		
			
			|  |  |  | req.setMchid(payAccount.getSubMchId()); | 
		
	
		
			
			|  |  |  | req.setOut_trade_no(order.getOrderNumber()); | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | String response = WxPayV3.payQuery(payService, req); | 
		
	
		
			
			|  |  |  | if (StringUtils.isBlank(response)){ | 
		
	
		
			
			|  |  |  | log.error("pay common v3 query response is null."+JSON.toJSONString(req)); | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),"pay common v3 query response is null."+JSON.toJSONString(req)); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return getPayQueryResult(response); | 
		
	
		
			
			|  |  |  | }catch(WxPayException e) { | 
		
	
		
			
			|  |  |  | log.error("pay common v3 query response error",e); | 
		
	
		
			
			|  |  |  | if("ORDER_CLOSED".equals(e.getErrCode())){ | 
		
	
		
			
			|  |  |  | PayQueryAdapterResult result = new PayQueryAdapterResult(); | 
		
	
		
			
			|  |  |  | result.setCode(EnumProductOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getCode()); | 
		
	
		
			
			|  |  |  | result.setMsg(EnumProductOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getMessage()); | 
		
	
		
			
			|  |  |  | return result; | 
		
	
		
			
			|  |  |  | }else if("ORDER_NOT_EXIST".equals(e.getErrCode()) || "ORDERNOTEXIST".equals(e.getErrCode())){ | 
		
	
		
			
			|  |  |  | PayQueryAdapterResult result = new PayQueryAdapterResult(); | 
		
	
		
			
			|  |  |  | result.setCode(EnumProductOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()); | 
		
	
		
			
			|  |  |  | result.setMsg(EnumProductOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getMessage()); | 
		
	
		
			
			|  |  |  | return result; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(),e.getCustomErrorMsg()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception { | 
		
	
		
			
			|  |  |  | return getPayCommonQueryResult((String)statusObject.getData()).getCode(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public int queryPayStatusCode(WxPayOrder oldRecord,  WxAppinfo appInfo, WxPayAccount payAccount) | 
		
	
		
			
			|  |  |  | throws Exception { | 
		
	
		
			
			|  |  |  | return queryPayStatus(oldRecord, appInfo, payAccount).getCode(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayAdapterResult payOrderClose(WxAppinfo appInfo, WxPayOrder record,WxPayAccount payAccount) throws Exception { | 
		
	
		
			
			|  |  |  | return null; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayAdapterResult payOrderReverse(WxAppinfo appInfo, WxPayOrder record, WxPayAccount payAccount) | 
		
	
		
			
			|  |  |  | throws Exception { | 
		
	
		
			
			|  |  |  | return super.payOrderReverse(appInfo, record, payAccount,payAccount.getSubMchId()); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayAdapterResult payOrderPush(String openId,WxAppinfo appInfo, WxBatchOrder batchOrder,WxPayOrder payOrder) throws Exception { | 
		
	
		
			
			|  |  |  | return null; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public File getQrcode(WxAppinfo appinfo,String pageUrl,int type,String sceneParam)  throws Exception{ | 
		
	
		
			
			|  |  |  | return super.getQrCode(appinfo, pageUrl, type, sceneParam); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public String getScheme(WxAppinfo appinfo, String pageUrl, String sceneParam,Long expireTime) throws Exception { | 
		
	
		
			
			|  |  |  | return super.generateScheme(appinfo, pageUrl, sceneParam,expireTime); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public PayAdapterResult noCreatePay(WxPayOrder record, WxComposeOrder composeOrder, List<WxOrder> childOrders) { | 
		
	
		
			
			|  |  |  | throw new MallinkException(ErrorCode.SYS_PARAMETER_ERROR); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | @Override | 
		
	
		
			
			|  |  |  | public void sendSubscribeMsg(WxAppinfo appinfo, WxTemplateMsg wxTemplateMsg, String openId, String toPage, Map<String, String> param) throws Exception { | 
		
	
		
			
			|  |  |  | super.subscribeMsg(appinfo,wxTemplateMsg,openId,toPage,param); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | } |