博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA微信扫码支付及微信App支付开发(模式二)完整功能实现
阅读量:4288 次
发布时间:2019-05-27

本文共 23629 字,大约阅读时间需要 78 分钟。

一,准备工作

事前申请一个商家版的微信公众号(目前微信支付只有商家版公众号可开通),然后开通微信支付功能,并做相应的配置。

申请开通微信公众号和开通微信支付需要等待审核,一般都5个工作日左右。开通成功后,需要获取配置信息:wx.pay.appid=********

wx.pay.mchid=******
wx.pay.key=**************
wx.pay.secret=*********

其中appid和secret可以在公众平台找着,mchid和key则在商户平台找到,特别是key(即API_KEY)要在商户平台设置好。本项目中这些配置通过properties文件放在***-payment-service工程的resource根路径下。

在编码之前,还需要登录微信商户平台配置支付回调URL,此配置作为支付成功后回调接口的域名。如果配置的URL为:http://www.abc.com/, 你的支付回调路径则可设置为:http://www.abc.com/api/payment/wxNotify。

二,编写代码

本项目我是用SpringBoot的微服务开发的,项目结构如下:

我们先看看Service接口

再看看Service的实现类:

@Service(value = "paymentService")public class PaymentServiceImpl implements PaymentService {		private static Logger LOGGER = LoggerFactory.getLogger(PaymentServiceImpl.class);	@Value("${project.service.env}")	private String PROJECT_ENV;		@Value("${hcc.pay.domain}")	private String payDomain;		@Autowired	private PaymentRecordMapper paymentRecordMapper;		@Autowired	private PaymentNotifyMapper paymentNotifyMapper;			@Override	@Transactional(readOnly=false,rollbackFor={Exception.class})	public Map
wxAppPayment(String orderId, double money) throws Exception { LOGGER.info("【微信App支付】 统一下单开始, 订单编号="+orderId); SortedMap
resultMap = new TreeMap
(); //生成支付金额 double payAmount = PayUtil.getPayAmountByEnv(PROJECT_ENV, money); //添加或更新支付记录 int flag = this.addOrUpdatePaymentRecord(orderId, payAmount, PayConstant.PAY_METHOD_WX,PayConstant.PAY_TRADE_TYPE_APP, false, null); if(flag < 0){ resultMap.put("returnCode", "FAIL"); resultMap.put("returnMsg", "此订单已支付!"); LOGGER.info("【微信App支付】 此订单已支付!"); }else if(flag == 0){ resultMap.put("returnCode", "FAIL"); resultMap.put("returnMsg", "支付记录生成或更新失败!"); LOGGER.info("【微信App支付】 支付记录生成或更新失败!"); }else{ //统一下单 Map
resMap = this.wxUnifieldOrder(orderId, PayConfig.TRADE_TYPE_APP, payAmount); if(PayConstant.SUCCESS.equals(resMap.get("return_code")) && PayConstant.OK.equals(resMap.get("return_msg"))){ //封装参数返回 resultMap.put("appid", PayConfig.WX_APP_ID);//前面配置中的appid resultMap.put("partnerid", PayConfig.WX_MCH_ID);//前面配置中的mchid resultMap.put("prepayid", resMap.get("prepay_id")); resultMap.put("package", "Sign=WXPay"); resultMap.put("noncestr", PayUtil.makeUUID(32)); resultMap.put("timestamp", PayUtil.getCurrentTimeStamp()); resultMap.put("sign", PayUtil.createSign(resultMap,PayConfig.WX_KEY)); resultMap.put("returnCode", "SUCCESS"); resultMap.put("returnMsg", "OK"); LOGGER.info("【微信App支付】统一下单成功,返回参数:"+resultMap); }else{ resultMap.put("returnCode", resMap.get("return_code")); resultMap.put("returnMsg", resMap.get("return_msg")); LOGGER.info("【微信App支付】统一下单失败,失败原因:"+resMap.get("return_msg")); } } return resultMap; } @Override public Map
wxQrPayment(String orderId, double money) throws Exception { LOGGER.info("【微信扫码支付】 开始下单, 订单编号="+orderId+",支付金额="+money); double payAmount = PayUtil.getPayAmountByEnv(PROJECT_ENV,money); Map
retMap = new HashMap
(); //添加或更新支付记录 int flag = this.addOrUpdatePaymentRecord(orderId, payAmount, PayConstant.PAY_METHOD_WX,PayConstant.PAY_TRADE_TYPE_QR,false, null); if(flag < 0){ retMap.put("returnCode", "FAIL"); retMap.put("returnMsg", "此订单已支付!"); LOGGER.info("【微信扫码支付】 此订单已支付!"); }else if(flag == 0){ retMap.put("returnCode", "FAIL"); retMap.put("returnMsg", "支付记录生成或更新失败!"); LOGGER.info("【微信扫码支付】 支付记录生成或更新失败!"); }else{ //微信统一下单 Map
map = this.wxUnifieldOrder(orderId,PayConfig.TRADE_TYPE_NATIVE,payAmount); //下单后返回状态 if(PayConstant.SUCCESS.equals(map.get("return_code")) && PayConstant.OK.equals(map.get("return_msg"))) { retMap.put("returnCode", map.get("return_code")); retMap.put("returnMsg", PayConstant.OK); retMap.put("codeUrl",map.get("code_url")); retMap.put("payAmount",String.valueOf(payAmount)); retMap.put("orderName", BaseConstants.PLATFORM_COMPANY_NAME); retMap.put("payMethod", "微信扫码支付"); retMap.put("queryUrl", this.getNotifyUrl(PayConstant.PAY_TYPE_WX)); LOGGER.info("【微信扫码支付】统一下单成功!"); }else{ retMap.put("returnCode", map.get("return_code")); retMap.put("returnMsg", map.get("return_msg")); LOGGER.info("【微信扫码支付】统一下单失败,失败原因:"+map.get("return_msg")); } retMap.put("orderNo",orderId); } return retMap; }@Override @Transactional(readOnly=false,rollbackFor={Exception.class}) public int wxNotify(Map
map) throws Exception{ Integer flag = 0; //支付订单编号 String orderNo = (String)map.get("out_trade_no"); //检验是否需要回调 if(this.isNotifyAgain(orderNo)){ //此处写更新支付信息和订单状态逻辑 } return flag; } /** *

微信支付统一下单

* * @param orderId 订单编号 * @param tradeType 支付类型 * @return * @throws Exception */ private Map
wxUnifieldOrder(String orderId,String tradeType, double payAmount) throws Exception{ //封装参数 SortedMap
paramMap = new TreeMap
(); paramMap.put("appid", PayConfig.WX_APP_ID); paramMap.put("mch_id", PayConfig.WX_MCH_ID); paramMap.put("nonce_str", PayUtil.makeUUID(32)); paramMap.put("body", BaseConstants.PLATFORM_COMPANY_NAME); paramMap.put("out_trade_no", orderId); paramMap.put("total_fee", PayUtil.moneyToIntegerStr(payAmount)); paramMap.put("spbill_create_ip", PayUtil.getLocalIp()); paramMap.put("notify_url", this.getNotifyUrl(PayConstant.PAY_TYPE_WX));//此处为要配置的回调地址 paramMap.put("trade_type", tradeType); paramMap.put("sign", PayUtil.createSign(paramMap,PayConfig.WX_KEY)); //转换为xml String xmlData = PayUtil.mapToXml(paramMap); //请求微信后台 String resXml = HttpUtils.postData(PayConfig.WX_PAY_UNIFIED_ORDER, xmlData); LOGGER.info("【微信支付】 统一下单响应:\n"+resXml); return PayUtil.xmlStrToMap(resXml); } @Override public int addOrUpdatePaymentRecord(String orderNo, double payAmount, int payType, String tradeType, boolean isPayment, String tradeNo) throws Exception{ PaymentRecord record = null; if(null == (record = paymentRecordMapper.findPaymentRecordByorderNo(orderNo))) { record = new PaymentRecord(); //封装对应参数,并添加一条支付信息,状态为“待支付” return paymentRecordMapper.insert(record); }else{ record.set...(); //此处是对已改变的参数进行更新 record.setUpdateTime(new Date()); return paymentRecordMapper.updateByPrimaryKey(record); } } /** *

检查是否需要再次回调更新订单

* * @param orderNo * @return */ private boolean isNotifyAgain(String orderNo){ //根据订单编号,查询对应支付信息,如果此条支付状态为已支付,返回TRUE,否则返回false //这样做的目的是防止多次调回调接口平凡刷新支付信息 } /** *

根据不同环境获取回调Api地址

* * @return */ private String getNotifyUrl(){ //服务域名 String serverDomain = PayConfig.PRO_SERVER_DOMAIN; if(BaseConstants.PLATFORM_ENV_DEV.equals(PROJECT_ENV)){ serverDomain = PayConfig.TEST_SERVER_DOMAIN; } return serverDomain + PayConstant.WX_PAY_CALLBACK_URL; }}

再看看这里的PayUtil工具类:

public class PayUtil {	static Logger log = LogManager.getLogger(PayUtil.class.getName());	/**	 * 获取当前机器的ip	 *	 * @return String	 */	public static String getLocalIp(){		InetAddress ia=null;		String localip = null;        try {            ia=ia.getLocalHost();            localip=ia.getHostAddress();        } catch (Exception e) {            e.printStackTrace();        }		return localip;        	}		/**	 * Map转换为 Xml	 * 	 * @param data	 * @return Xml	 * @throws Exception	 */	public static String mapToXml(SortedMap
map) throws Exception { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //防止XXE攻击 documentBuilderFactory.setXIncludeAware(false); documentBuilderFactory.setExpandEntityReferences(false); DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder(); org.w3c.dom.Document document = documentBuilder.newDocument(); org.w3c.dom.Element root = document.createElement("xml"); document.appendChild(root); for (String key: map.keySet()) { String value = map.get(key); if (value == null) { value = ""; } value = value.trim(); org.w3c.dom.Element filed = document.createElement(key); filed.appendChild(document.createTextNode(value)); root.appendChild(filed); } TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); DOMSource source = new DOMSource(document); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); transformer.transform(source, result); String output = writer.getBuffer().toString(); try { writer.close(); } catch (Exception ex) { } return output; } /** * 创建签名Sign * * @param key * @param parameters * @return */ public static String createSign(SortedMap
parameters,String key){ StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet(); Iterator
it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); if(entry.getValue() != null || !"".equals(entry.getValue())) { String v = String.valueOf(entry.getValue()); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } } sb.append("key=" + key); String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); return sign; } /** * XML转换为Map * * @param strXML * @return Map * @throws Exception */ public static Map
getMapFromXML(String strXML) throws Exception { try { Map
data = new HashMap
(); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); //防止XXE攻击 documentBuilderFactory.setXIncludeAware(false); documentBuilderFactory.setExpandEntityReferences(false); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); org.w3c.dom.Document doc = documentBuilder.parse(stream); doc.getDocumentElement().normalize(); NodeList nodeList = doc.getDocumentElement().getChildNodes(); for (int idx = 0; idx < nodeList.getLength(); ++idx) { Node node = nodeList.item(idx); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element element = (org.w3c.dom.Element) node; data.put(element.getNodeName(), element.getTextContent()); } } try { stream.close(); } catch (Exception ex) { ex.printStackTrace(); } return data; } catch (Exception ex) { throw ex; } } /** * 生成随机数 * * @return */ public static String makeUUID(int len) { return UUID.randomUUID().toString().replaceAll("-", "").substring(0, len); } /** * 获取当前的Timestamp * * @return */ public static String getCurrentTimeStamp() { return Long.toString(System.currentTimeMillis()/1000); } /** * 获取当前的时间 * @return */ public static long getCurrentTimestampMs() { return System.currentTimeMillis(); } /** * 获取当前工程url * * @param request * @return */ public static String getCurrentUrl(HttpServletRequest request){ return request.getScheme() +"://" + request.getServerName() + ":" +request.getServerPort() +request.getContextPath(); } /** * Xml字符串转换为Map * * @param xmlStr * @return */ public static Map
xmlStrToMap(String xmlStr){ Map
map = new HashMap
(); Document doc; try { doc = DocumentHelper.parseText(xmlStr); Element root = doc.getRootElement(); List children = root.elements(); if(children != null && children.size() > 0) { for(int i = 0; i < children.size(); i++) { Element child = (Element)children.get(i); map.put(child.getName(), child.getTextTrim()); } } } catch (DocumentException e) { e.printStackTrace(); } return map; } public static String getSceneInfo(String wapUrl,String name){ Map
> map = new HashMap
>(); if(!StringUtils.isEmpty(wapUrl) && !StringUtils.isEmpty(name)){ /*{"h5_info": {"type":"Wap","wap_url": "https://pay.qq.com","wap_name": "腾讯充值"}}*/ Map
childmap = new TreeMap
(); childmap.put("type", "Wap"); childmap.put("wap_url",wapUrl); childmap.put("wap_name", name); map.put("h5_info", childmap); return JSON.toJSONString(map); } return null; } /** * 转换金额型到整型 * @param money * @return */ public static String moneyToIntegerStr(Double money){ BigDecimal decimal = new BigDecimal(money); int amount = decimal.multiply(new BigDecimal(100)) .setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); return String.valueOf(amount); } /** * 除去数组中的空值和签名参数 * @param sArray 签名参数组 * @return 去掉空值与签名参数后的新签名参数组 */ public static Map
paraFilter(Map
sArray) { Map
result = new HashMap
(); if (sArray == null || sArray.size() <= 0) { return result; } for (String key : sArray.keySet()) { String value = sArray.get(key); if (value == null || value.equals("") || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) { continue; } result.put(key, value); } return result; } /** * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串 * @param params 需要排序并参与字符拼接的参数组 * @return 拼接后字符串 */ public static String createLinkString(Map
params) { List
keys = new ArrayList
(params.keySet()); Collections.sort(keys); String prestr = ""; for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); String value = params.get(key); if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符 prestr = prestr + key + "=" + value; } else { prestr = prestr + key + "=" + value + "&"; } } return prestr; } /** * 根据不同环境生成支付金额 * 生产环境支付金额为实际要支付钱数,测试环境做了处理便于测试人员测试 * * @param env * @param money * @param payType * @return */ public static double getPayAmountByEnv(String env,Double money){ double pay_money = 0.01; //测试环境 if(BaseConstants.PLATFORM_ENV_DEV.equals(env)){ if(money>10000){ pay_money = 0.03; }else if(money>1000){ pay_money = 0.02; }else{ pay_money = 0.01; } return pay_money; }else{ //生成环境 return money; } }}

支付配置类PayConfig:

public class PayConfig {	//微信支付类型	//NATIVE--原生支付	//JSAPI--公众号支付	//MWEB--H5支付	//APP -- app支付	public static final String TRADE_TYPE_NATIVE = "NATIVE";	public static final String TRADE_TYPE_JSAPI = "JSAPI";	public static final String TRADE_TYPE_MWEB = "MWEB";	public static final String TRADE_TYPE_APP = "APP";				//服务器域名	public static String PRO_SERVER_DOMAIN;	public static String TEST_SERVER_DOMAIN;	//微信公众号参数	public static String WX_APP_ID;	public static String WX_MCH_ID;	public static String WX_KEY;	public static String WX_APP_SECRET;		//微信支付API	public static final String WX_PAY_UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";		//参数	static{		Properties properties = new Properties();		try {			properties.load(PayConstant.class.getClassLoader().getResourceAsStream("payment_config.properties"));			PRO_SERVER_DOMAIN = (String) properties.get("pro.server.domain");			TEST_SERVER_DOMAIN = (String) properties.get("test.server.domain");			//wx pay			WX_APP_ID = (String) properties.get("wx.pay.appid");			WX_MCH_ID = (String) properties.get("wx.pay.mchid");            WX_KEY = (String) properties.get("wx.pay.key");            WX_APP_SECRET = (String) properties.get("wx.pay.secret");		} catch (Exception e) {			e.printStackTrace();		}	}}

 到这里为止,业务实现基本已经写完了,现在我们去看看接口层吧!

@RestController@RequestMapping(value = "/app/payment/")public class PaymentController {	private static Logger logger = LoggerFactory.getLogger(PaymentController.class);	@Value("${project.service.env}")	private String PROJECT_ENV;	@Value("${error.page}")	private String error_page;	@Value("${hcc.app.domain}")	private String orderDomain;	@Autowired	private PaymentService paymentService;		@Autowired	private RedisCacheService cacheService;		/**	 * App支付接口	 * 微信和支付宝统一下单入口	 * 	 * @param request	 * @return	 * @throws Exception	 */	@ResponseBody    @RequestMapping(value="appPay", method=RequestMethod.POST, produces = {"application/json;charset=UTF-8"})	public JSONObject toPay(HttpServletRequest request) throws Exception {		String requestStr = RequestStr.getRequestStr(request);		if (StringUtils.isEmpty(requestStr)) {			throw new ParamException();		}		JSONObject jsonObj = JSONObject.parseObject(requestStr);		if(StringUtils.isEmpty(jsonObj.getString("payType")) || StringUtils.isEmpty(jsonObj.getString("orderNo"))){		   	throw new ParamException();		}	   	//验证订单是否存在	   	String orderId = jsonObj.getString("orderNo");	   	OrderInfo orderInfo = getPayOrder(orderId);	   	if(orderInfo == null){	   		return AjaxUtil.renderFailMsg("订单不存在!");	   	}else if(orderInfo.getPayPrice() == null || orderInfo.getPayPrice() < 0.01){	   		return AjaxUtil.renderFailMsg("订单有误,请确认!");	   	}else if(orderInfo.getpStatus() != OrderConstant.PORDER_STATUS_YTJ){	   		String msg = orderInfo.getpStatus() == OrderConstant.PORDER_STATUS_YFK?"此订单已支付!":"无效的订单,请确认!";	   		return AjaxUtil.renderFailMsg(msg);	   	}else{	   		//微信支付		   	if(PayConstant.PAY_TYPE_WX.equals(jsonObj.getString("payType"))){			   	Map
resMap = paymentService.wxAppPayment(orderInfo.getOrderNo(),orderInfo.getPayPrice()); //判断微信统一下单是否成功 if("SUCCESS".equals(resMap.get("returnCode")) && "OK".equals(resMap.get("returnMsg"))){ //统一下单成功 resMap.remove("returnCode"); resMap.remove("returnMsg"); logger.info("【App支付服务】微信支付下单成功!"); return AjaxUtil.renderSuccessMsg(resMap); }else{ return AjaxUtil.renderFailMsg(resMap.get("returnMsg")); } }else if(PayConstant.PAY_TYPE_ALI.equals(jsonObj.getString("payType"))){ //支付宝支付 }else{ return AjaxUtil.renderParamFailMsg("请选择支付方式!"); } } } /** * 扫码支付接口 * 微信和支付宝统一下单入口 * * @param request * @return * @throws Exception */ @ResponseBody @RequestMapping(value="qrPay", method=RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) public JSONObject qrPay(HttpServletRequest request) throws Exception { String requestStr = RequestStr.getRequestStr(request); if (StringUtils.isEmpty(requestStr)) { throw new ParamException(); } JSONObject jsonObj = JSONObject.parseObject(requestStr); if(StringUtils.isEmpty(jsonObj.getString("payType")) || StringUtils.isEmpty(jsonObj.getString("orderNo"))){ throw new ParamException(); } //验证订单是否存在 String orderId = jsonObj.getString("orderNo"); OrderInfo orderInfo = getPayOrder(orderId); if(orderInfo == null){ return AjaxUtil.renderFailMsg("订单不存在!"); }else if(orderInfo.getPayPrice() == null || orderInfo.getPayPrice() < 0.01){ return AjaxUtil.renderFailMsg("订单有误,请确认!"); }else if(orderInfo.getpStatus() != OrderConstant.PORDER_STATUS_YTJ){ String msg = orderInfo.getpStatus() == OrderConstant.PORDER_STATUS_YFK?"此订单已支付!":"无效的订单,请确认!"; return AjaxUtil.renderFailMsg(msg); }else{ if(PayConstant.PAY_TYPE_WX.equals(jsonObj.getString("payType"))){ //微信支付扫码支付 Map
resMap = paymentService.wxQrPayment(orderInfo.getOrderNo(), orderInfo.getPayPrice()); //判断微信统一下单是否成功 if(PayConstant.SUCCESS.equals(resMap.get("returnCode")) && PayConstant.OK.equals(resMap.get("returnMsg"))){ resMap.remove("returnCode"); resMap.remove("returnMsg"); logger.info("【Web扫码支付服务】微信支付下单成功!"); return AjaxUtil.renderSuccessMsg(resMap); }else{ return AjaxUtil.renderFailMsg(resMap.get("returnMsg")); } }else if(PayConstant.PAY_TYPE_ALI.equals(jsonObj.getString("payType"))){ //支付宝扫码支付 }else{ return AjaxUtil.renderParamFailMsg("请选择支付方式!"); } } } /** *

获取二维码

* * @param request * @param response * @throws Exception */ @ResponseBody @RequestMapping(value="qrCodeImg", method=RequestMethod.GET, produces = {"application/json;charset=UTF-8"}) public void getQrCodeImg(HttpServletRequest request,HttpServletResponse response) throws Exception{ //获取参数 String codeUrl = request.getParameter("codeUrl"); if(!StringUtils.isEmpty(codeUrl)){ CodeUtil.generateQrCodeImg(codeUrl,response.getOutputStream()); }else{ throw new ParamException(); } } /** * 微信支付完成回调Api * * @param request * @param response * @throws Exception */ @RequestMapping(value="wxNotify") public void wxNotify(HttpServletRequest request,HttpServletResponse response) throws Exception { InputStream inputStream = request.getInputStream(); //获取请求输入流 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len=inputStream.read(buffer))!=-1){ outputStream.write(buffer,0,len); } outputStream.close(); inputStream.close(); Map
map = BeanToMap.getMapFromXML(new String(outputStream.toByteArray(),"utf-8")); logger.info("【微信支付回调】 回调数据: \n"+map); String resXml = ""; String returnCode = (String) map.get("return_code"); if ("SUCCESS".equalsIgnoreCase(returnCode)) { String returnmsg = (String) map.get("result_code"); if("SUCCESS".equals(returnmsg)){ //更新数据 int result = paymentService.wxNotify(map); if(result > 0){ //支付成功 resXml = "
" + "
" + "
"+"
"; } }else{ resXml = "
" + "
" + "
" + "
"; logger.info("支付失败:"+resXml); } }else{ resXml = "" + "" + "
" + "
"; logger.info("【订单支付失败】"); } logger.info("【微信支付回调响应】 响应内容:\n"+resXml); //做出响应 response.getWriter().print(resXml); } /** *

查询订单支付是否完成

* * @param request * @param response * @return * @throws Exception */ @ResponseBody @RequestMapping(value="queryPayStatus") public JSONObject queryPayStatus(HttpServletRequest request,HttpServletResponse response) throws Exception { String requestStr = RequestStr.getRequestStr(request); if (StringUtils.isEmpty(requestStr)) { throw new ParamException(); } JSONObject jsonObj = JSONObject.parseObject(requestStr); if(StringUtils.isEmpty(jsonObj.getString("orderNo"))){ throw new ParamException(); } PaymentRecord record = paymentService.queryPaymentStatusById(jsonObj.getString("orderNo")); if(record != null && record.getStatus){ //此处可根据自己想要返回的数据封装返回,“已支付”可用封装的Map返回 return AjaxUtil.renderSuccessMsg(“已支付”); }else{ return AjaxUtil.renderFailMsg("未支付!"); } } /** *

通过Http请求订单服务获取订单信息

* * @param orderNo * @return * @throws Exception */ private OrderInfo getPayOrder(String orderNo) throws Exception{ //更新订单状态 String reqUrl = orderDomain + "order/findOrderByPrimary"; SortedMap params = new TreeMap(); params.put("orderId", orderNo); JSONObject json = JSONObject.parseObject(HttpUtils.sendPostWithSign(reqUrl, params)); if("0000".equals(json.get("responseCode"))){ OrderInfo orderInfo = JSONObject.parseObject(json.getString("data"),OrderInfo.class); if(orderInfo != null){ return orderInfo; } } return null; }}]]>

到此为止,所有的编码工作已完成。

 三,测试(用扫码支付)

选择要购买的商品,然后下单,再去发起支付。

单击“去支付”按钮,跳转到二维码支付页面:

 扫码支付完成后,显示二维码的页面会跳转到支付成功页面(带微信支付成功logo),并有3s的倒计时,然后跳转到“订单详情”页。

 

本人有完整的电商支付微服务代码(微信支付和支付宝支付),如果需要,请关注本人微信公众号留言,或通过公众号加我私人微信联系,希望能和大家一起学习进步! 

 

转载地址:http://ijlgi.baihongyu.com/

你可能感兴趣的文章
mysql为什么使用B+树作为索引的结构
查看>>
mysql索引总结(1)-mysql 索引类型以及创建(文章写的不错!!!)
查看>>
聊聊CAS - 面试官最喜欢问的并发编程专题
查看>>
Spring Boot 中使用一个注解轻松将 List 转换为 Excel 下载
查看>>
高并发环境下,先操作数据库还是先操作缓存?
查看>>
MySQL Explain详解
查看>>
一直搞不清楚什么是读写分离,主从复制的原理,今天总算搞懂了
查看>>
消息队列 mq 必会面试题
查看>>
线程池的工作原理是啥?能手写一个线程池吗?
查看>>
一口气说出 6种 延时队列的实现方案,大厂offer稳稳的
查看>>
原来redis这么简单,跟着文章操作一遍你就会了
查看>>
Redis两种持久化机制RDB和AOF详解(面试常问,工作常用)
查看>>
事务隔离级别中的可重复读能防幻读吗?
查看>>
老伙计,关于JDK并发包,这些不为人知的秘密你知道多少?
查看>>
图片的左右切换
查看>>
进级的RecyclerView——LRecyclerView
查看>>
Android 利用Gradle实现app的环境分离
查看>>
Android系统篇之----Binder机制和远程服务调用
查看>>
JavaScript DOM 属性
查看>>
Gradle 实现 Android 多渠道定制化打包
查看>>