欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

淘宝API开发ISV订购页面必看

程序员文章站 2022-07-15 14:16:35
...
在开发阿里软件的ISV应用时,你可能需要开发一个订购页面来让用户订购你的ISV应用。
     对于开发思路,我在这里通过用户订购的流程来说明一下,估计可能会好理解一些。
1、用户点出购买,购买请求会提交到阿里软件平台。
2、阿里软件平台根据用户购买的情况配置参数,传到你的ISV。
3、ISV根据参数判断是新订、续订还是资源购买来跳转到相应的页面。(这里就需要你开发一个action,来接收参数并进行判断。还需要开发相当的页面)
4、用户选择了订购的内容后,由ISV组织参数(主要是内容的价格等),将这些参数传递给阿里平台。(这里又需要一个action)
5、用户在阿里平台进行付款,阿里平台转到支付宝平台(这一步无需我们干预)
6、付款成功后,支付宝平台将交易信息传递给阿里软件平台。(也无需我们干预)
7、阿里软件将本次交易的明细和结果通知给ISV,isv进行处理(这需要我们定义的一action来接收参数)

在上架之前要设置价格策略:如下页面
淘宝API开发ISV订购页面必看
            
    
    博客分类: 阿里软件 StrutsApacheServletSQL 
其中有两个地址很关键:
1、软件价格描述地址:是一个订购url,此url的作用是进行巡辑判断,以进入不同的订购页面,如新订页面、续订页面、资源购买等。相当于我们上面所说的第3条,这个url具体到一个action。
2、通知url地址:此url的作用是接收平台发送过来的订购业务通知。相当于我们上面所说的第7条的action



明白了上面所说的,下面是java版本的开发订购的一个例子:
1、订购页面开发所需要的接口:IOrderConstanct

public interface IOrderConstanct {
	public static final String PARAMETER_SIGNATURE="signature";//签名 
	public static final String PARAMETER_SUBSCTYPE="subscType" ;//订购类型 
	public static final String PARAMETER_APPID="appId" ;//所订购的软件id 
	public static final String PARAMETER_APPEND="appEnd" ;//软件服务的截止时间 
	public static final String PARAMETER_GMTSTART="gmtStart";//订单开始时间 
	public static final String PARAMETER_SUBSCEND="subscEnd" ;//订购控制记录的结束时间 
	public static final String PARAMETER_CTRLPARAMS="ctrlParams" ;//控制参数 
	public static final String PARAMETER_RETURNURL="returnUrl" ;//订购页面参数回传地址 
	public static final String PARAMETER_POSTDATA="postData" ;//订购页面要原样回传的参数 
	public static final String PARAMETER_CODE="4df0c2b038f511ddbba29f5366f82354";//注册时获得的安全码 
	public static final String PARAMETER_SIGN="sign"; 
	public static final String PARAMETER_APPINSTANCEID="appInstanceId";//应用实例ID 
	public static final String PARAMETER_EVENT="event";//**类型,新订、续订、资源订购及退订 
	public static final String PARAMETER_USERID="userId";//用户ID 
	public static final String PARAMETER_SUBSCID="subscId";//订单ID 
	public static final String PARAMETER_GMTEND="gmtEnd";//订单结束时间 
	public static final String PARAMETER_TOTALAMOUNT="totalAmount";//订单总金额 
	public static final String PARAMETER_AMOUNT="amount";//实付金额 
	public static final String PARAMETER_RENTAMOUNT="rentAmount";//月租额 
	public static final String PARAMETER_RESOURCEAMOUNT="resourceAmount";//购买资源金额 
	public static final String PARAMETER_COUPONAMOUTN="couponAmount";//红包 
 
}

2、下面开发软件价格描述地址所指的action,接收平台传过来的参数。假如我的地址是这样填写的http://127.0.0.1:8080/demoproj/order.do,这个action就是OrderAction。
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.alisoft.sip.sdk.isv.SignatureUtil;
import //导入上面定义的接口IOrderConstanct所在的包


public class OrderAction extends Action {

	/**
	 * 当用户点击您的应用,要开通订购时,平台会向这个OrderAction post许多信息,在这个action中要做的就是接收这些参数,并根据参数进行判断是新订、续订、还是资源订购,并输出到具体页面 
	 * Method execute
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 */
	@SuppressWarnings("unchecked")
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		//接收所有从平台传递过来的参数
		@SuppressWarnings("unused")
		Enumeration en = request.getParameterNames();
		Map<String,Object> map = new HashMap<String, Object>();
		while(en.hasMoreElements()){//将传入的参数全部放在map中
			String key =(String) en.nextElement();
			map.put(key, request.getParameter(key));
		}
		String sig = (String) map.get(IOrderConstanct.PARAMETER_SIGNATURE);//因为加密时会去掉这个参数,所以先进行保存
		String sign = SignatureUtil.Signature(map, (String) map.get(IOrderConstanct.PARAMETER_CODE));//进行签名
		
		HttpSession session = request.getSession();
		session.setAttribute("signature", sig); //将加密文本放入session
		session.setAttribute("subscType", map.get(IOrderConstanct.PARAMETER_SUBSCTYPE)); //订购资源类型
		session.setAttribute("appId", map.get(IOrderConstanct.PARAMETER_APPID)); 
		session.setAttribute("appInstanceId",map.get(IOrderConstanct.PARAMETER_APPINSTANCEID) ); 
		session.setAttribute("appEnd", map.get(IOrderConstanct.PARAMETER_APPEND)); 
		session.setAttribute("subscEnd", map.get(IOrderConstanct.PARAMETER_SUBSCEND)); 
		session.setAttribute("ctrlParams", map.get(IOrderConstanct.PARAMETER_CTRLPARAMS)); 
		session.setAttribute("postdata", map.get(IOrderConstanct.PARAMETER_POSTDATA));//订购页面要原样回传的参数 
		session.setAttribute("returnUrl", map.get(IOrderConstanct.PARAMETER_RETURNURL)); //订购页面参数回传地址
		session.setAttribute("gmtStart", map.get(IOrderConstanct.PARAMETER_GMTSTART));//订单开始时间 
		
		/* 
		* 先验证应用ID及签名是否一致,然后根据订购类型跳转到不同的页面(0-新订、1、2-续订、3-资源订购) 
		*/ 
		if(map.get(IOrderConstanct.PARAMETER_APPID).equals("1840")&&sig.equals(sign)){ //验证应用ID,这里要换成你的应用ID
			if("0".equals(map.get(IOrderConstanct.PARAMETER_SUBSCTYPE))){//转到新订页面
				return mapping.findForward("subsc"); 
			}else if("1".equals(map.get(IOrderConstanct.PARAMETER_SUBSCTYPE))){//转到未到期续订页面
				return mapping.findForward("neworder"); 
			}else if("2".equals(map.get(IOrderConstanct.PARAMETER_SUBSCTYPE))){ //转到到期续订页面
				return mapping.findForward("timeoutorder"); 
			}else if("3".equals(map.get(IOrderConstanct.PARAMETER_SUBSCTYPE))){//转到资源订购页面
				return mapping.findForward("buyorder"); 
			}
				return mapping.findForward("error"); //如果出错了,转到错误处理页面
		}else{
			return mapping.findForward("error"); 
		}
	}
}

3、我们开发一个订购页面。在这里,我们只开发一个页面作为说明: (在你开发时可能中气情况要有几个页面)
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 
<title>无标题文档</title> 
</head> 
<body> 
	<form action="./orderback.do" method="OST"> 
		<%--request.getSession().setAttribute("a",request.getSession().getAttribute("a"));--%> 
		<%--out.println(application.getAttribute("b")) ;--%> 
		<table width="400" border="1"align="center"> 
			<tr> 
				<td>资源套餐一</td> 
				<td><input name="buy" type="radio" value="10" checked>10元</input> </td> 
			</tr> 
			<tr> 
				<td>资源套餐二</td> 
				<td><input name="buy" type="radio" value="20">20元 </td> 
			</tr> 
			<tr> 
				<td>资源套餐三</td> 
				<td><input name="buy" type="radio" value="30">30元 </td> 
			</tr> 
			<tr> 
				<td>月租</td> 
				<td><select name="rent" size="1"> 
					<option value="50">50元/月</option> 
					<option value="100">100元/月</option> 
					</select> </td> 
			</tr> 
			<tr align="center"> 
				<td colspan="2"><input type="submit" name="Submit" value="续订"> </td>
 			</tr> 

		</table> 
	</form> 
</body> 
</html>
注:此页面是内嵌在阿里平台的页面中的。图中虚线以下就是我们自己做的订购页面,虚线以上是平台提供的页面。如图:
淘宝API开发ISV订购页面必看
            
    
    博客分类: 阿里软件 StrutsApacheServletSQL 
4、因为平台是内嵌了ISV提供的订购页面,所以,当用户选择好订购参数后,应用要把用户的订购参数回传给平台。我们在上面的代码中可以看到,form中的actoin写的是orderback.do,它是映射到orderbackAction的。当用户提交参数后,orderbackAction将获得订购参数。orderbackAction根据订购类型把信息回传给平台,并跳转回平台。OrderbackAction代码如下:
import java.io.UnsupportedEncodingException; 
import java.net.URLEncoder; 
import java.text.SimpleDateFormat; 
import java.util.Calendar; 
import java.util.HashMap; 
import java.util.Map; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;
 
import org.apache.struts.action.Action; 
import org.apache.struts.action.ActionForm; 
import org.apache.struts.action.ActionForward; 
import org.apache.struts.action.ActionMapping; 

import com.alisoft.sip.sdk.isv.SignatureUtil;
import com.constanct.*; 

public class OrderbackAction extends Action { 
	
	public static java.text.SimpleDateFormat TIME_FORMATER = new SimpleDateFormat("yyyy-MM-dd");//时间格式 
	private String postData;//平台要求的原样回传的参数 
	private String returnUrl;//回传url 
	private String subscType;//订购类型 
	private double amount;//金额 
	private double rentAmount; 
	private double resourceAmount; 
	private String ctrlParams;//控制参数 
	private String signature;//签名 
	public ActionForward execute(ActionMapping mapping, ActionForm form, 
								HttpServletRequest request, HttpServletResponse response) { 
		/* 
		* 从servletcontext中读取需要的参数 
		*/ 
		subscType=(String)request.getSession().getAttribute("subscType"); //订购类型 
		postData=(String)request.getSession().getAttribute("postdata");// 订购页面要原样回传的参数
		returnUrl=(String)request.getSession().getAttribute("returnUrl"); //订购页面参数回传地址
		String gmtStart=(String)request.getSession().getAttribute("gmtStart"); //订单开始时间 
		String gmtEnd=addMon(gmtStart,1);//计算订单结束时间,即订单开始时间加上订购时间,此处写死为一个月,但可在订购页面中让用户自行选择订购时间 
		/* 
		* 订购类型不同时,传给平台的参数也是不同的。所以,根据订购类型,分别进行参数的组织 
		*/ 
		Map<String, Object> map=new HashMap<String, Object>(); 
		if("0".equals(subscType)){//新订 
			map.put("postData", postData); //原样传回的参数
			map.put("gmtStart",gmtStart); //开始时间
			map.put("gmtEnd", gmtEnd); //结束时间
			rentAmount=Integer.parseInt(request.getParameter("rent")); //页面传递过来的参数,按时间判断订购金额
			resourceAmount=Integer.parseInt(request.getParameter("buy")); //页面传递过来的参数,按套餐判断订购金额
			map.put("rentAmount", rentAmount); 
			map.put("resourceAmount", resourceAmount); 
			amount=rentAmount+resourceAmount; //将金额相加
			map.put("amount", amount); 
			ctrlParams="amount=10&rent=50"; //这地方什么意思,说是控制参数,到现在没看懂,数字是写死的吗?估计不是写死的。可amount一定会比rent要大,结果这里却是小于。如果有看懂的请留言
			map.put("ctrlParams", ctrlParams); 
		}else if("1".equals(subscType)){//未到期续订,不能修改订购开始时间,及控制参数 
			map.put("postData", postData); 
			map.put("gmtEnd", gmtEnd); 
			rentAmount=Integer.parseInt(request.getParameter("rent")); 
			resourceAmount=Integer.parseInt(request.getParameter("buy")); 
			map.put("rentAmount", rentAmount); 
			map.put("resourceAmount", resourceAmount); 
			amount=rentAmount+resourceAmount; 
			map.put("amount", amount); 
		}else if("2".equals(subscType)){//到期续订 
			map.put("postData", postData); 
			map.put("gmtStart",gmtStart); 
			map.put("gmtEnd", gmtEnd); 
			rentAmount=Integer.parseInt(request.getParameter("rent")); 
			resourceAmount=Integer.parseInt(request.getParameter("buy")); 
			map.put("rentAmount", rentAmount); 
			map.put("resourceAmount", resourceAmount); 
			amount=rentAmount+resourceAmount; 
			map.put("amount", amount); 
			ctrlParams="amount=10&rent=50"; //??
			map.put("ctrlParams", ctrlParams); 
		}else {//订购资源,其中月租部分为零 
			map.put("postData", postData); 
			resourceAmount=Integer.parseInt(request.getParameter("buy")); 
			map.put("resourceAmount", resourceAmount); 
			map.put("rentAmount", 0); 
			map.put("amount", resourceAmount); 
			ctrlParams="amount=10&rent=50"; //??
			map.put("ctrlParams", ctrlParams); 
			map.put("description", "中文"); 
		} 
		signature=SignatureUtil.Signature(map, DemoConstant.PARAMETER_CODE);//签名 
		map.put("signature", signature); 
		/* 
		* 组织参数 
		*/ 
		StringBuffer buffer = new StringBuffer(); 
		boolean notFirst = false; 
		for (Map.Entry<String, ?> entry : map.entrySet()) { 
		if (notFirst) { 
		buffer.append("&"); 
		} else { 
		notFirst = true; 
		} 
		Object value = entry.getValue(); 
		buffer.append(entry.getKey()).append("=").append( 
		encodeURL(value) ); 
		} 
		String queryString=buffer.toString(); 
		
		/* 
		* 跳转回平台,并带上相关的订购参数 
		*/ 
		try{ 
		response.sendRedirect(returnUrl+"?"+queryString); 
		}catch(Exception e){ 
		e.printStackTrace(); 
		
		} 
		return null; 
	} 
	
	/* 
	* 编码 
	*/ 
	private String encodeURL(Object target) { 
		String result = (target != null) ? target.toString() : ""; 
		try { 
			result = URLEncoder.encode(result, "GBK"); 
		} catch (UnsupportedEncodingException e) { 
			e.printStackTrace(); 
		} 
		return result; 
	} 
	
	/* 
	* 日期计算 
	*/ 
	public static String addMon(String s, int n) { 
		Calendar cd=null; 
		try {
			cd = Calendar.getInstance(); 
			cd.setTime(TIME_FORMATER.parse(s)); 
			cd.add(Calendar.MONTH, n);//增加一月 
			cd.add(Calendar.DATE, -1); 	
		} catch (Exception e) { 
			e.printStackTrace(); 
		} 
	
		return TIME_FORMATER.format(cd.getTime()); 
	} 

}
跳转回平台后,出现如下页面:淘宝API开发ISV订购页面必看
            
    
    博客分类: 阿里软件 StrutsApacheServletSQL 
5、点击付款后,会跳到支付宝支付中心,用户进行付款。付款成功后,平台会发送相关信息给通知url。这又是一action,用于接收平台传递过来的交易情况的信息:
package com.order.struts.action; 

import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.Map; 

import javax.servlet.ServletContext; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.struts.action.Action; 
import org.apache.struts.action.ActionForm; 
import org.apache.struts.action.ActionForward; 
import org.apache.struts.action.ActionMapping; 

import com.alisoft.sip.sdk.isv.SignatureUtil;
import //导入上面IOrderConstanct所在的包
public class InformAction extends Action { 

	private String sign; 
	@SuppressWarnings("unchecked")
	public ActionForward execute(ActionMapping mapping, ActionForm form, 
								HttpServletRequest request, HttpServletResponse response){
		Enumeration e=(Enumeration)request.getParameterNames(); //获得平台传过来的订购付款信息 
		Map<String, Object> map = new HashMap<String, Object>(); 
		ServletContext context = this.servlet.getServletContext(); 
		context.removeAttribute("gmtStart"); 
		while(e.hasMoreElements()){ 
			String params=(String)e.nextElement(); 
			map.put(params, request.getParameter(params)); 
			context.setAttribute(params, request.getParameter(params)); 
		} 
		String sig=(String)map.get(DemoConstant.PARAMETER_SIGNATURE); 
		sign=SignatureUtil.Signature(map, DemoConstant.PARAMETER_CODE);//根据得到的参数进行自签名 
		if(sign.equals(sig)){//验证签名 
			if(map.get(DemoConstant.PARAMETER_EVENT).equals("subsc")){//新订 
				/* 
				*添加订购关系; 
				*添加月租信息,资源信息; 
				*建立账户信息,账户充值; 
				*/ 
			}else if(map.get(DemoConstant.PARAMETER_EVENT).equals("renewAhead")){ 
				/* 
				* 未到期续订,修改月租信息,资源信息 
				*/ 
			}else if(map.get(DemoConstant.PARAMETER_EVENT).equals("renew")){ 
				/* 
				* 到期续订,修改月租信息,资源信息 
				*/ 
			}else if(map.get(DemoConstant.PARAMETER_EVENT).equals("resource")){ 
				/* 
				* 订购资源,修改资源信息 
				*/ 
			}else if(map.get(DemoConstant.PARAMETER_EVENT).equals("break")){ 
				/* 
				* 退订,删除订购关系,删除账户信息,释放资源 
				*/ 
			}else{ 
				/* 
				* error 
				*/ 
			} 
		} 
		return null; 
	} 
} 
至此,我们的收费页面开发就完成了。淘宝API开发ISV订购页面必看
            
    
    博客分类: 阿里软件 StrutsApacheServletSQL  淘宝API开发ISV订购页面必看
            
    
    博客分类: 阿里软件 StrutsApacheServletSQL  淘宝API开发ISV订购页面必看
            
    
    博客分类: 阿里软件 StrutsApacheServletSQL