渠道订单设计
- 目的
我们是提供分销服务的,一般的供销平台提供了代销和经销两种线上经营模式
代销:分销商无需拿货就可以直接销售并赚取差价,由供应商一件代发
经销:分销商直接从供应商处批量采购并囤货销售,享受更多折扣
1) 代销基本业务流程
2) 经销基本业务流程
而我们的系统是提供代销服务。就是分销商在其他的平台例如淘宝销售商品,生成订单反馈给我们系统,我们系统需要把外部订单转换成我们自己的订单,
生成和他对应的供应商订单,然后进入我们的系统的订单流程,最终由我们的仓储平台发货。因此,我们需要获取不同渠道的订单, 转换成我们系统的的订单。
- 条件
1. 要获取不同渠道的订单,就要涉及到对方的开放平台(API) 。因此,首先要解决如何对接开放平台?对接开放平台一般都需要用户授权,授权流程遵循oauth2.0协议。
例如,如果您的应用和淘宝开放平台对接后,需要获取用户隐私信息(如:商品、订单、收藏夹等),为保证用户数据的安全性与隐私性,您的应用需要取得用户的授权。在这种情况下,您的应用需要引导用户完成“使用淘宝帐号登录并授权”的流程。 淘宝的Taobao ID(淘帐号)产品,采用国际通用的OAuth2.0标准协议,作为用户身份验证与授 权协议,支持网站、手机客户端、桌面客户端。
淘宝的授权流程需要您有自己的web服务器,能够保存应用本身的密钥以及状态,可以通过https直接访问淘宝的授权服务器。
授权过程分为两个步骤:
上面的淘宝的授权流程就遵循oauth2.0协议。
2. 授权成功后,还需要通过调用api获取所属信息。api调用需要遵循对方的要求。例如淘宝的api调用方式
TOP 作为淘宝数据插槽,只要用户按照TOP的规范拼装一个正确的URL,通过HTTP请求到TOP,就能够拿到用户自己需要的数据。调用原理示意图如下(注: 淘宝 API <接口>采用 REST 风格,只需将所需参数拼装成http请求,即可调用。故支持 http 协议请求的程序语言,均可调用淘宝API,例如php、C#、asp、java、delphi 等。)
3. 获取了数据,还需要把数据转换成我们的自己的数据。
总的大体流程如下:
- 实现
针对上面的分析,我们需要实现oauth授权,api调用,csv导入和导出。
1.oauth授权
我们仅仅是oauth的web的client实现,虽然目前有很多流行的框架.例如oauth官方推荐的
调查了spring social,实现的方式很好,代理拦截+template模块化获取资源, 只是目前还不支持top,虽然已支持facebook, twitter,github等,如果自己实现工作量有点大。
spring security,还需要引入spring security这个框架,虽然先前我使用过,有点杀鸡焉用牛刀的感觉
Restlet是一个rest框架,和spring的实现有重叠。
最终选择了apache的实现,参照demo很容易实现,授权的流程。
@RequestMapping ("/authorize/{providerId}" ) public ModelAndView authorize( @PathVariable String providerId, Model model) throws OAuthSystemException, IOException { try { OauthTemplate oauth = getTemplate(providerId); OauthProviderConfig appOauth = oauth.getProviderConfig(); OAuthClientRequest request = OAuthClientRequest.authorizationLocation(appOauth.getAuthzEndpoint()).setClientId(appOauth.getClientId()).setRedirectURI(appOauth.getRedirectUri()) .setResponseType(ResponseType.CODE .toString()).setScope(appOauth.getScope()).setState(appOauth.getState()).buildQueryMessage(); return new ModelAndView(new RedirectView(request.getLocationUri())); } catch (Exception e) { model.addAttribute( "errorMsg" , "授权失败" ); logger.info( "authorize" , e); return new ModelAndView("redirect:/oauthClient/list.htm"); } } @RequestMapping (value = "/token/{providerId}" , method = RequestMethod.GET) public ModelAndView handleRedirect( @PathVariable String providerId, Model model, HttpServletRequest req) throws OAuthSystemException { try { OauthTemplate oauth = getTemplate(providerId); OauthProviderConfig appOauth = oauth.getProviderConfig(); // Create the response wrapper OAuthAuthzResponse oar = null ; oar = OAuthAuthzResponse. oauthCodeAuthzResponse(req); // Get Authorization Code String code = oar.getCode(); OAuthClientRequest request = OAuthClientRequest.tokenLocation(appOauth.getTokenEndpoint()).setClientId(appOauth.getClientId()).setClientSecret(appOauth.getClientSecret()) .setRedirectURI(appOauth.getRedirectUri()).setCode(code).setGrantType(GrantType.AUTHORIZATION_CODE).buildBodyMessage(); OAuthClient client = new OAuthClient(SSL_CLIENT); OAuthJSONAccessTokenResponse oauthResponse = client.accessToken(request, OAuthJSONAccessTokenResponse.class); Boolean oauthResult = channelService .saveInfo(oauth.convertResponse(oauthResponse)); model.addAttribute( "successFlag" , oauthResult); } catch (OAuthProblemException e) { logger.info( "oauth" , e); model.addAttribute( "errorMsg" , "授权失败" ); } return new ModelAndView("redirect:/oauthClient/list.htm"); }
2. 授权完成了,需要api调用,选择了top官方推荐的sdk模式,针对以后可能不同的渠道,例如还需要支持paipai,采用了模板模式
获取模板如
private OauthTemplate getTemplate(String appId) throws OAuthSystemException { OauthTemplate oauth = null ; for (OauthTemplate template : oauthTemplates ) { if (template.isProvider(appId)) { oauth = template; break ; } } if (oauth == null) { throw new OAuthSystemException("无效的用户请求" ); } return oauth; }
针对获取不同的资源,采取了命令模式,同时可以实现session token的拦截验证,目前,由于授权的限制,仅仅简单判定一下是否报错就可了。
public Map<String, Object> doAuthInfo(Integer cid, AuthInfo authInfo) throws OAuthSystemException { ChannelInfo info = channelService .getInfo(cid); if (info == null) { throw new OAuthSystemException("无效的请求 "); } Map<String, Object> resultMap = new HashMap<String, Object>(); resultMap.put( "flag" , Boolean.TRUE); try { OauthTemplate oauth = getTemplate(info.getProviderId()); authInfo.doExecute(info, oauth, resultMap); } catch (OAuthProblemException e) { logger.info( "授权错误" , e); resultMap.put( "flag" , Boolean.FALSE); resultMap.put( "redirect" , MessageFormat.format( "authorize/{0}.htm" , info.getProviderId())); } catch (Exception e) { logger.info( "请求资源错误" , e); resultMap.put( "flag" , Boolean.FALSE); } return resultMap; }
3.csv实现
采用第三方opencsv实现的。
- 结论
总的原则,还是面向对象的思想,解耦。
相关推荐
pigsmall 2020-11-19
SXIAOYI 2020-09-16
Ladyseven 2020-07-25
whileinsist 2020-06-24
gufudhn 2020-06-12
冰蝶 2020-06-05
LinuxAndroidAI 2020-06-04
supperme 2020-05-28
yaodilu 2020-05-10
e度空间 2020-04-27
云端漂移 2020-04-09
peterwzc 2020-03-17
有心就有方向 2012-09-03
ebuild 2013-05-14
donghedonghe 2013-05-31
tdeclipse 2011-02-28
linuxprobe0 2013-04-15
linuxprobe0 2013-04-01