针对APP的后台支付代码(微信和支付宝)

非淡泊无以明志,非宁静无以致远。这篇文章主要讲述针对APP的后台支付代码(微信和支付宝)相关的知识,希望能为你提供帮助。
APP支付: 1.微信支付: 这是app支付时,一个完整的流程

针对APP的后台支付代码(微信和支付宝)

文章图片
1.1首先要去微信开放平台注册,并创建APP
针对APP的后台支付代码(微信和支付宝)

文章图片
1.2取得微信支付的权限
针对APP的后台支付代码(微信和支付宝)

文章图片
1.3 商户平台有公众号平台和APP平台两种,一定要是APP平台,可以在下面这个地方查看
针对APP的后台支付代码(微信和支付宝)

文章图片
1.4 我们需要在商户平台和开放平台上获取到以下数据: 开放平台: APPID、APP_SECRET:见1图。 商户平台: 秘钥(APP_KEY):微信商户平台(pay.weixin.qq.com)--> 账户设置--> API安全--> 密钥设置 商户号(MCH_ID):微信商户平台(pay.weixin.qq.com)--> 账户设置--> 商户信息--> 微信支付商户号 数字证书(微信退款需要使用):微信商户平台(pay.weixin.qq.com)--> 账户设置--> API安全--> 证书下载 2.支付宝的操作流程简单,文档清楚(略) 3准备工作结束,我的产品是使用Hbuilder开发的html5的APP,后端是依托于java Web程序。工作流程参照时序图。主要代码如下,详情见文件 其中用到一些工具方法  或者客户端创建代码都在链接里面有,我放在了码云上面 https://gitee.com/muziTM/payDemo 3.1  入口
/** * 支付类包含支付宝和微信 * @author Tianming_Li * */ @Controller @RequestMapping("/payController") public class PayController { //订单 @Autowired OrdersService orderService; //付费 @Autowired PayService payService; //退费 @Autowired RefundService refundService; //支付成功回调 @Autowired CallBackService callBackService; /** * 下单 * @param outTradeNo * @param payType * @param request * @param response * @param modelMap * @return */ @RequestMapping("/pay") public String pay(@RequestParam(name="outTradeNo") String outTradeNo,@RequestParam(name="payType") String payType, HttpServletRequest request,HttpServletResponse response, ModelMap modelMap){ //根据订单号获取到订单信息 Orders order = orderService.selectOrdersInfoByOutTradeNo(outTradeNo); if("wxpay".equals(payType)){ return payService.wxPay(order, request, response, modelMap); }else{ return payService.aliPay(order); } } /** * 退款 * @param outTradeNo * @param payType * @param request * @param response * @return */ @RequestMapping("/refunds") public String refunds(@RequestParam(name="outTradeNo") String outTradeNo,@RequestParam(name="payType") String payType, HttpServletRequest request,HttpServletResponse response){ //根据订单号获取到订单信息 Orders order = orderService.selectOrdersInfoByOutTradeNo(outTradeNo); if("wxpay".equals(payType)){ return refundService.wxRefund(order, request, response); }else{ return refundService.aliRefund(order); } }/** * 接收微信支付成功通知 * * @param request * @param response * @throws IOException */@RequestMapping(value = "https://www.songbingjia.com/getWxPayNotify") public void getWxPayNotify(HttpServletRequest request, HttpServletResponse response) throws IOException { callBackService.wxCallBack(request, response); } /** * 接收支付宝支付成功回调 * @param request * @param response * @throws IOException */ @RequestMapping("/getAliPayNotify") public void getAliPayNotify(HttpServletRequest request, HttpServletResponse response) throws IOException { callBackService.aliCallBack(request, response); }}

3.2 支付代码

/** * 支付处理 * @author Tianming_Li * */ @Service("payService") public class PayServiceImpl implements PayService {protected static final Log logger = LogFactory.getLog(PayServiceImpl.class); @Override public String wxPay(Orders order, HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) { BaseDao dao = DaoUtils.getDao("sys"); StringBuilder sb = new StringBuilder(); sb.append("SELECT * FROM WX_PAY_CONFIG WHERE YY_ID = ‘"); sb.append(order.getYyId()); sb.append("‘"); //获取到微信配置参数 WxPayConfig appPayConfig = dao.getObjectBySql(sb.toString(), WxPayConfig.class); Map< String, Object> map = new HashMap< String, Object> (); //初始化一个请求对象 WxRequestHandler wxRequestHandler = new WxRequestHandler(request, response); String payFee = order.getPayMoney(); int intPayFee = (int) (Float.valueOf(payFee) * 100); String nonceStr = WxUtils.getNonceStr(); String outTradeNo = order.getOutTradeNo(); String timestamp = WxUtils.getTimeStamp(); wxRequestHandler.setParameter("appid", appPayConfig.getAppId()); //appId wxRequestHandler.setParameter("mch_id", appPayConfig.getMchId()); //商户号 wxRequestHandler.setParameter("nonce_str", nonceStr); //随机字符串 wxRequestHandler.setParameter("body", appPayConfig.getBody()); //商品描述 wxRequestHandler.setParameter("notify_url", appPayConfig.getNotifyUrl()); //通知地址 wxRequestHandler.setParameter("out_trade_no", outTradeNo); wxRequestHandler.setParameter("spbill_create_ip", request.getRemoteAddr()); wxRequestHandler.setParameter("total_fee", String.valueOf(intPayFee)); wxRequestHandler.setParameter("trade_type", "APP"); //注意签名生成方式,具体见官方文档 wxRequestHandler.setParameter("sign", wxRequestHandler.createMD5Sign(appPayConfig.getAppKey())); String prepayid; try { prepayid = wxRequestHandler.sendPrepay(); if (prepayid != null & & !prepayid.equals("")) { String signs ="appid=" + appPayConfig.getAppId() + "& noncestr=" + nonceStr + "& package=Sign=WXPay" + "& partnerid="+ appPayConfig.getPartnerId() //商户id + "& prepayid=" + prepayid + "& timestamp=" + timestamp + "& key=" + appPayConfig.getAppKey(); //商户平台---api安全---密钥 map.put("code", 200); map.put("info", "success"); map.put("prepayid", prepayid); map.put("sign", WxUtils.getMD5Encode(signs, "utf8").toUpperCase()); map.put("appid", appPayConfig.getAppId()); map.put("timestamp", timestamp); // 等于请求prepayId时的time_start map.put("noncestr", nonceStr); // 与请求prepayId时值一致 map.put("package", "Sign=WXPay"); // 固定常量 map.put("partnerid", appPayConfig.getPartnerId()); //商户id } else { map.put("code", 400); map.put("info", "获取prepayid失败"); } } catch (Exception e) { map.put("code", 405); map.put("info", "系统异常"); }return JSONUtils.toJSON(map); }@Override public String aliPay(Orders order) { //获取配置参数 BaseDao dao = DaoUtils.getDao("sys"); StringBuilder sb = new StringBuilder(); sb.append("SELECT * FROM ALI_PAY_CONFIG WHERE YY_ID = ‘"); sb.append(order.getYyId()); sb.append("‘"); AliPayConfig appPayConfig = dao.getObjectBySql(sb.toString(), AliPayConfig.class); // 实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息 AlipayClient alipayClient = new DefaultAlipayClient(appPayConfig.getUrl(), appPayConfig.getAppId(), appPayConfig.getRsaPrivateKey(), appPayConfig.getFormat(), appPayConfig.getCharset(), appPayConfig.getPublicKey(), appPayConfig.getSigntype()); // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); // SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); //销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY BeanUtils.copy(order, model); //将订单信息复制到model类中 request.setBizModel(model); // 回调地址指向回调函数example: https://ip:port/payController/getAliPayNotify.do request.setNotifyUrl(appPayConfig.getNotifyUrl()); String orderStr = ""; try { // 这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); orderStr = response.getBody(); logger.info("订单str:" + orderStr); } catch (AlipayApiException e) { logger.info(e.getMessage()); } return orderStr; }}

  3.2回调代码
@Service("callBackService") public class CallBackServiceImpl implements CallBackService {private static final Log LOGGER = LogFactory.getLog(CallBackServiceImpl.class); public static final String SUCCESS = "SUCCESS"; @SuppressWarnings("unchecked") @Override public void wxCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter writer = response.getWriter(); InputStream inputstream = request.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; while((len = inputstream.read(b))!= -1){ outputStream.write(b, 0, len); } String result = new String(outputStream.toByteArray(), "utf-8"); inputstream.close(); outputStream.close(); Map< String, String> map = null; //解析微信通知返回的信息 try { map = WxUtils.doXMLParse(result); } catch (JDOMException e) { LOGGER.info("微信回调失败:"+e.getMessage()); } // 若支付成功,则告知微信服务器收到通知 if (SUCCESS.equals(map.get("return_code")) & & SUCCESS.equals(map.get("result_code"))) {/** * ... * 回调业务 *///微信会一直调用接口,直到我们返回SUCCESS String notifyStr = WxUtils.setXML(SUCCESS, ""); writer.write(notifyStr); writer.flush(); } }@Override public void aliCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException { LOGGER.info("进入支付宝回调"); // 获取支付宝GET过来反馈信息 String reqWay = ""; if ("GET".equals(request.getMethod())) { reqWay = "GET"; } Map< String, String> params = new HashMap< String, String> (); Map< ?, ?> requestParams = request.getParameterMap(); for (Iterator< ?> iter = requestParams.keySet().iterator(); iter.hasNext(); ) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 if ("GET".equals(reqWay)) { try { valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); } catch (UnsupportedEncodingException e) { LOGGER.info("不支持的编码:" + e.getMessage()); } } params.put(name, valueStr); } String tradeNo = request.getParameter("trade_no"); // 支付宝交易号 String tradeStatus = request.getParameter("trade_status"); // 支付状态 String outTradeNo = request.getParameter("out_trade_no"); // 系统订单号 String sellerId = request.getParameter("seller_id"); // 商户号LOGGER.info("支付宝交易号:" + tradeNo + ", 返回状态:" + tradeStatus + ",订单号:" + outTradeNo); Map< String, Object> map = new HashMap< String, Object> (); String result = ""; try { if ("TRADE_SUCCESS".equals(tradeStatus)) { /** * ... * 回调业务 */ } else { result = "fail"; // 为了保证不重复回调 } } catch (Exception e) { result = "fail"; } map.put(result, result); AliUtils.renderText(response, result); }}

3.4  微信退费的时候需要证书,密码默认是商户号,由于项目中使用了多个微信商户号,因此有多个证书,路径和密码放在了数据库中
public class WxRequestHandler{ /** * 退费 * @return */ public Map< String,String> sendWxChanel(String filePath,String pwd) throws Exception{ Map< String,String> map =null; Set es=this.getAllParameters().entrySet(); Iterator it=es.iterator(); StringBuilder sb = new StringBuilder("< xml> "); while(it.hasNext()){ Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); sb.append("< "+k+"> "+v+"< /"+k+"> "); } sb.append("< /xml> "); String params=sb.substring(0); String requestUrl = this.getGateUrl(); TenpayHttpClient httpClient = new TenpayHttpClient(); httpClient.setReqContent(requestUrl); String resContent = ""; //filepath 文件路径 pwd 密码 if (httpClient.callHttpPost(requestUrl, params,true,filePath,pwd)) { resContent = httpClient.getResContent(); map=WxUtils.doXMLParse(resContent); } return map; }}

 
【针对APP的后台支付代码(微信和支付宝)】 

    推荐阅读