赞
踩
用户在请求支付的时候,服务端就要向微信支付发起统一下单
接口:这里就会填入商户内部订单的编号、付款金额、通知地址等,统一下单接口就会返回调起支付的必要参数。服务器就需要将这个参数返回给客户端。
微信服务器验证正确后会自动通知微信弹出输入密码框。
用户在输入了支付密码之后,微信支付系统将会根据你在统一下单接口时候填入的通知地址
,返回一些数据信息。服务端在处理了这些信息之后,就要返回微信支付系统需要的返回参数。
流程,如下所示:
用户在发起退款申请,服务器就调起申请退款
接口,输入退款结果通知。
推荐使用异步通知进行处理:因为微信退款产生,并不是即时到帐,通常出现这个提示之后的几分钟之内,钱款就会到账。
result_code
为fail:有可能是商户出现问题 <dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-WxPay</artifactId>
<version>2.8.0</version>
</dependency>
wx: miniApp: appId: appSecret: pay: mchId: machSerialNumber: mchSecret: # 商户证书文件路径 # 请参考“商户证书”一节 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3 cert: apiclient_cert.p12 # 请参考“回调通知注意事项” https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_8&index=6 doMain: android: appId: appSecret: ios: appId: appSecret:
@ConfigurationProperties(prefix = "wx") @Component @Data public class WxProperties { private MiniApp miniApp; private Pay pay; private Android android; private Ios ios; @Data public static class MiniApp{ private String appId; private String appSecret; } @Data public static class Pay{ private String mchId; private String machSerialNumber; private String mchSecret; private String cert; private String doMain; } @Data public static class Ios{ private String appId; private String appSecret; } @Data public static class Android{ private String appId; private String appSecret; } }
/** * 付款订单的预支付会话标识 * <p> 此接口对应的是 V2 的版本 * 1. 检查订单是否能够付款 * 2. 处理微信商户平台返回的参数 * 3. 设置订单付款状态 */ @Transactional(rollbackFor = Exception.class) public Object prepay(Integer originType) { UnifiedOrderModel.UnifiedOrderModelBuilder unifiedOrderModelBuilder = UnifiedOrderModel.builder(); // 商户号 unifiedOrderModelBuilder.mch_id(wxProperties.getPay().getMchId()); // 商品描述: 订单编号 unifiedOrderModelBuilder.body(""); // 订单编号:订单中获取 unifiedOrderModelBuilder.out_trade_no(""); // 价格单位:(分) 整数 unifiedOrderModelBuilder.total_fee(""); // 附加数据 unifiedOrderModelBuilder.attach(""); // 随机字符串 unifiedOrderModelBuilder.nonce_str(WxPayKit.generateStr()); //支付的ip地址 unifiedOrderModelBuilder.spbill_create_ip(ServletUtil.getClientIP(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest())); // 支付回调地址 unifiedOrderModelBuilder.notify_url(wxProperties.getPay().getDoMain() + "/other/wx/notifyUrl"); /* * 订单有效期为15min。用户在14min59s唤起支付,在支付界面停留了2s(此时,已经过了交易期限),不能够让用户在进行微信支付 * 就需要设置交易的开始时间以及结束时间 */ DateTime orderCreateTime = DateUtil.date(); // 交易开始时间 unifiedOrderModelBuilder.time_start(DateUtil.format(orderCreateTime, DatePattern.PURE_DATETIME_PATTERN)); // 交易结束时间 : 15分钟 unifiedOrderModelBuilder.time_expire(DateUtil.format(DateUtil.offsetMinute(orderCreateTime, 15), DatePattern.PURE_DATETIME_PATTERN)); if (originType == 0) { // 小程序appId unifiedOrderModelBuilder.appid(wxProperties.getMiniApp().getAppId()); // 小程序中的openId(ios以及android是没有的) unifiedOrderModelBuilder.openid(""); // 交易方式 unifiedOrderModelBuilder.trade_type(TradeType.JSAPI.getTradeType()); } else if (originType == 1) { // 安卓appId unifiedOrderModelBuilder.appid(wxProperties.getAndroid().getAppId()); // 交易方式 unifiedOrderModelBuilder.trade_type(TradeType.APP.getTradeType()); } else if (originType == 2) { // ios的appId unifiedOrderModelBuilder.appid(wxProperties.getIos().getAppId()); // 交易方式 unifiedOrderModelBuilder.trade_type(TradeType.APP.getTradeType()); } Map<String, String> requestParams = unifiedOrderModelBuilder.build().createSign(wxProperties.getPay().getMchSecret(), SignType.MD5); logger.info("统一下单请求参数:" + requestParams); // 向微信发送统一下单请求 String resultXml = WxPayApi.pushOrder(false, requestParams); logger.info("统一下单请求参数:" + resultXml); // 将获取结果集xml变为Map Map<String, String> resultMap = WxPayKit.xmlToMap(resultXml); String returnCode = resultMap.get("return_code"); String returnMsg = resultMap.get("return_msg"); // 检查是否连接到微信支付 if (!WxPayKit.codeIsOk(returnCode)) { return returnMsg; } // 检查交易是否成功 String resultCode = resultMap.get("result_code"); if (!WxPayKit.codeIsOk(resultCode)) { return returnMsg; } // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回 Map<String, String> returnParams = null; if (originType == 0) { returnParams = WxPayKit.miniAppPrepayIdCreateSign(wxProperties.getMiniApp().getAppId(), resultMap.get("prepay_id"), wxProperties.getPay().getMchSecret(), SignType.MD5); logger.info("小程序调起支付的参数: " + returnParams); } else if (originType == 1) { returnParams = WxPayKit.appPrepayIdCreateSign(wxProperties.getAndroid().getAppId(), wxProperties.getPay().getMchId(), resultMap.get("prepay_id"), wxProperties.getPay().getMchSecret(), SignType.MD5); logger.info("Android调起支付的参数: " + returnParams); } else if (originType == 2) { returnParams = WxPayKit.appPrepayIdCreateSign(wxProperties.getIos().getAppId(), wxProperties.getPay().getMchId(), resultMap.get("prepay_id"), wxProperties.getPay().getMchSecret(), SignType.MD5); logger.info("IOS调起支付的参数: " + returnParams); } /* * 数据库处理:设置状态为未支付、设置支付方式等业务处理 */ return returnParams; }
public Object payNotify(HttpServletRequest request, HttpServletResponse response) { Map<String, String> analysisMap = WxPayKit.xmlToMap(HttpKit.readData(request)); logger.info("支付结果通知:" + analysisMap); // 验证支付 if (WxPayKit.verifyNotify(analysisMap, wxProperties.getPay().getMchSecret(), SignType.MD5)) { // 与微信通讯是否成功 if (WxPayKit.codeIsOk(analysisMap.get("return_code"))) { Map<String, String> resultParams = new HashMap<>(); resultParams.put("return_code", "SUCCESS"); resultParams.put("return_msg", "OK"); //支付成功 if (WxPayKit.codeIsOk(analysisMap.get("result_code"))) { // !得到的订单编号中能否查询相应的订单 ! // !校验返回的订单金额是否与商户的订单金额一致 ! // !该通知是否已经处理过 ! /* * 数据库的业务处理 */ return WxPayKit.toXml(resultParams); } else { // 交易失败 // ! 用户输错密码 银行卡余额不足 不走微信支付结果通知接口的失败 ! log.info("微信支付交易失败"); return WxPayKit.toXml(resultParams); } }else { log.info("微信回调:微信通讯失败: {}", analysisMap.get("return_msg")); } } log.info("非法微信回调"); return null; }
/** * @param orderNo 订单编号 * @param originType 订单来源 */ public Object refund(String orderNo,Integer originType) { /* * 查看能否搜寻到该订单 */ /* * 查看订单是否能够退款 */ // 微信退款 String appid = null; // 0.小程序 1.安卓 2.iOS if (originType == 0) { appid = wxProperties.getMiniApp().getAppId(); } else if (originType == 1) { appid = wxProperties.getAndroid().getAppId(); } else { appid = wxProperties.getIos().getAppId(); } Map<String, String> params = RefundModel.builder() .appid(appid) .mch_id(wxProperties.getPay().getMchId()) .nonce_str(WxPayKit.generateStr()) .out_trade_no(orderNo) .out_refund_no("R" + orderNo.substring(1)) .total_fee("") .refund_fee("") .notify_url(wxProperties.getPay().getDoMain() + "/wx/refundUrl") .build() .createSign(wxProperties.getPay().getMchSecret(), SignType.MD5); Map<String, String> resultMap = null; try { resultMap = WxPayKit.xmlToMap(WxPayApi.orderRefund(false, params, new ClassPathResource("apiclient_cert.p12").getURL().getPath(), wxProperties.getPay().getMchId())); } catch (IOException e) { return new Exception("微信调起支付退款异常" + e.getMessage()); } String returnCode = resultMap.get("return_code"); String returnMsg = resultMap.get("return_msg"); if (!WxPayKit.codeIsOk(returnCode)) { log.info("微信退款失败:{}", returnMsg); return "微信退款失败"; } log.info("微信退款成功"); return "微信退款成功"; }
public String refundUrl(HttpServletRequest request){ String xmlMsg = HttpKit.readData(request); Map<String, String> params = WxPayKit.xmlToMap(xmlMsg); log.info("退款通知:{}", params); String returnCode = params.get("return_code"); if (WxPayKit.codeIsOk(returnCode)) { String reqInfo = params.get("req_info"); Map<String, String> decryptData = WxPayKit.xmlToMap(WxPayKit.decryptData(reqInfo, wxProperties.getPay().getMchSecret())); log.info("退款通知解密后的数据:{}", decryptData); Map<String, String> xml = new HashMap<String, String>(2); xml.put("return_code", "SUCCESS"); xml.put("return_msg", "OK"); // 退款是否成功 if (WxPayKit.codeIsOk(decryptData.get("refund_status"))) { /* * 当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过, * 如果没有处理过再进行处理,如果处理过直接返回结果成功。 */ return WxPayKit.toXml(xml); }else { if (("CHANGE".equals(decryptData.get("refund_status")))) { /* * “退款异常”:当用户使用银行卡支付时,当银行卡状态不正常或银行卡错误时,又退回用户微信零钱失败 */ log.info("微信退款发生退款异常"); } else { /* * “退款关闭”:余额不足或者其他情况 */ log.info("微信退款发生退款关闭异常"); } return WxPayKit.toXml(xml); } } log.info("微信退款回调错误:{}", params.get("return_msg")); return null; }
/** * 微信支付订单的查询 * * @param orderNo 订单号 * @param originType 订单来源 0.小程序 1.安卓 2.iOS */ public Map<String, String> orderQuery(String orderNo, Integer originType) { String appid = null; // 0.小程序 1.安卓 2.iOS if (originType == 0) { appid = wxProperties.getMiniApp().getAppId(); } else if (originType == 1) { appid = wxProperties.getAndroid().getAppId(); } else { appid = wxProperties.getIos().getAppId(); } Map<String, String> params = OrderQueryModel.builder() .appid(appid) .mch_id(wxProperties.getPay().getMchId()) .out_trade_no(orderNo) .nonce_str(WxPayKit.generateStr()) .build() .createSign(wxProperties.getPay().getMchSecret(), SignType.MD5); Map<String, String> resultMap = WxPayKit.xmlToMap(WxPayApi.orderQuery(params)); String return_code = resultMap.get("return_code"); String return_msg = resultMap.get("return_msg"); if (!WxPayKit.codeIsOk(return_code)) { log.info("查询微信支付订单失败:{}", return_msg); } log.info("查询微信支付订单:{}", resultMap); return resultMap; }
/** * 微信退款订单的查询 * * @param orderNo 订单号 * @param originType 订单来源 0.小程序 1.安卓 2.iOS */ public Map<String, String> refundQuery(String orderNo, Integer originType) { String appid = null; // 0.小程序 1.安卓 2.iOS if (originType == 0) { appid = wxProperties.getMiniApp().getAppId(); } else if (originType == 1) { appid = wxProperties.getAndroid().getAppId(); } else { appid = wxProperties.getIos().getAppId(); } Map<String, String> params = RefundQueryModel.builder() .appid(appid) .mch_id(wxProperties.getPay().getMchId()) .out_trade_no(orderNo) .nonce_str(WxPayKit.generateStr()) .build() .createSign(wxProperties.getPay().getMchSecret(), SignType.MD5); Map<String, String> resultMap = WxPayKit.xmlToMap(WxPayApi.orderRefundQuery(false, params)); String returnCode = resultMap.get("return_code"); String returnMsg = resultMap.get("return_msg"); if (!WxPayKit.codeIsOk(returnCode)) { log.info("查询退款信息失败:{}", returnMsg); } log.info("查询退款信息:{}", resultMap); return resultMap; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。