阿里巴巴 YunOS开放平台
系统支付SDK集成说明文档
v 2.0.0
注册并登录YunOS开放平台,按照系统提示完成身份验证手机号绑定等。
进入“控制台”,左侧栏中打开应用配置并创建应用,按要求填写应用信息,如下图,创建应用后请等待工作人员审核,审核通过后继续。
(1)进入 应用管理 页,点击“查看”,如图:
(2)点击“查看”,进入应用功能页,如图一:打开“客户端SDK”,跳转到“生成最新SDK”的页面;如下图:
(3)点击“生成SDK”,进入如下图:
(4)根据提示操作,“点击开通”,跳转到开通页面按照流程申请支付功能需要的key和secret;如下图:
请仔细阅读上传页面中的注意事项,上传需要集成支付服务的APK文件,勾选“支付服务”选项,“生成最新SDK”。
注意: 如果应用的APK文件比较大,生成 SDK 的时候建议生成一个同样包名和 keystore 的空包进行上传,以节约时间。
下载生成的SDK后,解压,内容如下:
将其中的 libs/ res/ 和 AndroidManifest.xml 的内容合并至待集成的工程目录。
注意事项:
-keepattributes Signature
-keep class sun.misc.Unsafe { *; }
-keep class com.taobao.** {*;}
-keep class com.alibaba.** {*;}
-keep class com.alipay.** {*;}
-dontwarn com.taobao.**
-dontwarn com.alibaba.**
-dontwarn com.alipay.**
-keep class com.ut.** {*;}
-dontwarn com.ut.**
-keep class com.ta.** {*;}
-dontwarn com.ta.**
-keep class com.aliyun.violet.** {*;}
-keep class com.yunos.violet.** {*;}
-keep class com.yunos.upay.client.** {*;}
-keep class com.snowfish.**{*;}
-dontwarn com.unity3d.**
-keep class com.unity3d.**{*;}
支付服务是YunOS系统具有的安全,高效的支付能力。 由支付sdk和系统支付服务组成。 支付sdk提供调用支付宝支付和调用系统支付服务的能力。 系统 支付服务会提供用户更多的支付方式,如支付宝,短信支付等。
SDK初始化
SDK初始化必须在Application中进?行
static void asyncInit(Context, InitResultCallback callback);
callback 用于回调初始化结果。
import com.alibaba.sdk.android.AlibabaSDK;
import com.alibaba.sdk.android.callback.InitResultCallback;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
/* SDK初始化必须在Application中进?行 */
AlibabaSDK.asyncInit(this, new InitResultCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int code, String message) {
//失败原因可能下载sdk的应?用签名与当前应?用签名不?一致
}
});
}
}
1 接口描述:
为便于支付订单统计及管理,在SDK初始化完成后,建议开发者在适当的时机(如用户的登录状态更新时)调用以下接口设置用户信息。 开发者设置的用户信息将会在支付服务的后台管理页面中与订单关联,可以此作为对用户退款及售后的依据。
无
void setUserInfo(Map<String, String> map);
map 可选的key有: userID, nick
YunpayService yunpayService = AlibabaSDK.getService(YunpayService.class);
HashMap<String, String> map = new HashMap();
map.put("userID", "xxxxx");
map.put("nick", "xxxxx");
yunpayService.setUserInfo(map);
1 接口描述:
通过YunPayService的showPage接口对订单发起支付
void showPayPage(Activity activity, String orderInfo, PayCallback callback);
orderInfo: 发起支付的订单, 将以下参数,通过key=value&进行拼接生成的字符串.
参数 |
参数名称 |
参数说明 |
参数要求 |
bizOrderNo |
订单号 |
|
必选 |
subject |
商品名称 |
|
必选 |
currency |
货币代码 |
当前只支持人民币:CNY |
必选 |
price |
商品金额 |
单位分 |
必选 |
notifyUrl |
服务器异步通知路径 |
支付服务服务器主动通知应用服务器 |
可以不传,但不能传空字符串,端口: 80 或 443 |
publicKey |
公钥 |
支付服务颁发给应用的公钥 |
必选 |
extraData |
开发者自定义数据 |
|
可以不传,但不能传空字符串 |
sign |
签名 |
签名是将其余字段按照key的字母升序排列,以key=value&进行拼接,然后进行HmacSHA256加密的结果 |
必选 |
YunpayService yunpayService = AlibabaSDK.getService(YunpayService.class);
if (yunpayService == null) {
//插件没有初始化,无法获取 YunpayService"
return;
}
String id = UUID.randomUUID().toString();//生成订单id
String extraData = "开发者自定义的额外信息,保存在支付服务服务器";
String publicKey = PUBLIC_KEY;
// 注意:订单字符串一定要按照key字母升序排列,例如:"bizOrderNo=%s¤cy=%s&price=%s&publicKey=%s&subject=%s"
String origin = "bizOrderNo=" + id + "¤cy=" + currency + "&extraData=" + extraData + "¬ifyUrl=" + url + "&price=" + price + "&publicKey=" + publicKey + "&subject=" + subject;
//将未编码的字符串进行HmacSHA256 进行加密
String sign = DemoUtils.sign(origin, SECRET);
//对订单参的Value值数做 URL encode,生成传输用的字符串
String order = "bizOrderNo=" + encode(id) + "¤cy=" + encode(currency) + "&extraData=" + encode(extraData) + "¬ifyUrl=" + encode(url) + "&price=" + encode(price) + "&publicKey=" + encode(publicKey) + "&subject=" + encode(subject) + "&sign=" + encode(sign);
//创建支付结果的回调
PayCallback callback = new PayCallback() {
@Override
public void onPay(Result result) {
//result.getCode() 获取的的是支付状态码
if (result.getCode() == 9000) {
//TODO:成功
} else {
//TODO:失败。4000: 订单无效,6001:用户取消,6002: 网路错误,8000: 正在处理
}
}
};
//发起支付, 必须在UI线程中调用
yunpayService.showPayPage(this, orderInfo, callback);
错误码 |
含义 |
备注 |
钱是否到账 |
4000 |
订单无效 |
订单已失效(过期或其他原因关闭) |
否 |
6001 |
用户取消 |
|
否 |
6002 |
网络错误 |
|
否 |
8000 |
正在处理 |
小概率场景,要与服务端再确认 |
待确认 |
9000 |
支付成功 |
|
是 |
对支付结果进行查询
无
QueryOrderStatusResult queryOrderStatus(Context context, String queryString);
YunpayService yunpayService = AlibabaSDK.getService(YunpayService.class);
/*
* 这个函数不能在UI线程调用。建议作为后台service来调用
* queryString 是将key:bizOrderNo, publicKey 按照key的字母升序,以
* key=value&进行拼接,然后再结尾附加签名信息
* 格式:"bizOrderNo=%s&publicKey=%s&sign=%s"
* 其中sign是对其之前字符串进行 HmacSHA256 进行加密的结果。例如:
*/
QueryOrderStatusResult result =
yunpayService.queryOrderStatus(getApplicationContext(),
queryString);
/*
* 1. 当result.getCode() == 200时:可以通过result.getOrderStatus()获取
* 订单状态. 订单状态有:"WAIT_PAY":待支付,"PAY_SUCCESS": 交易成功,
* "PAY_CLOSED":交易关闭
* 2. 当result.getCode() 其他值见错误码定义
*/
错误码 |
含义 |
建议 |
200 |
成功 |
|
2 |
订单过期 |
重建订单 |
3 |
网络错误 |
检查网络 |
7 |
创建订单失败 |
|
10001 |
Server系统错误 |
稍后再试,或联系服务端开发人员 |
10002 |
参数错误 |
检查传递的参数 |
10003 |
签名错误 |
检查对参数的签名,请检查参数及对参数的签名 |
支付服务端面向开发者服务端提供的接口
1 接口描述:
支付服务对开发者的请求数据处理完成后,会将处理的结果数据通过服务器主动通知的方式通知给开发者服务器。
2 通知触发条件:
支付成功
3 参数说明:
参数 |
参数名称 |
参数说明 |
是否可空 |
样例 |
notifyTime |
通知时间 |
通知的发送时间。格式为yyyy-MM-dd HH:mm:ss |
否 |
2014-11-24 00:22:07 |
notifyType |
通知类型 |
通知的类型。 |
否 |
pay |
notifyId |
通知ID |
通知ID,可用作校验使用 |
否 |
bb7620a82f057fadfadfa1d05d05be77fc3w |
bizOrderNo |
业务订单号 |
开发者内部唯一订单号 |
否 |
1511111180 |
tradeNo |
支付服务交易号 |
该交易在支付服务系统中的交易流水号。最长64位。 |
否 |
2014112400001000340011111111 |
tradeStatus |
交易状态 |
取值范围: PAY_SUCCESS、PAY_CLOSED |
否 |
PAY_SUCCESS |
gmtCreate |
交易创建时间 |
该笔交易创建的时间。格式为yyyy-MM-dd HH:mm:ss。 |
否 |
2014-11-24 00:21:52 |
gmtPayment |
交易付款时间 |
该笔交易的买家付款时间。格式为yyyy-MM-dd HH:mm:ss。 |
可空 |
2014-11-24 00:22:07 |
totalAmount |
交易金额 |
该笔订单的总金额。请求时对应的参数,单位分 |
否 |
136 |
extraData |
开发自定义参数 |
开发者支付时提供的额外的自定义参数 |
可空 |
abc |
trade_platform |
三方 |
三方交易平台 |
可空 |
alipay |
trade_platform_no |
三方流水 |
三方交易平台流水号 |
可空 |
|
signType |
签名方式 |
HmacSHA256 |
否 |
HmacSHA256 |
sign |
签名 |
签名是按着其余字段(不包含signType)将key的字母按着升序,以key=value&进行拼接,然后进?HmacSHA256加密的结果,例如:bizOrderNo=%s&tradeNo=%s& tradeStatus=%s |
否 |
39528c90dda85058896ddb18505a661ddd72d2efc950e5236e54eac3aa5ab373 |
4 报文范例:
notifyTime=2016-05-24 20:34:27¬ifyType=pay¬ifyId=94640932674445476389&bizOrderNo=9b15b61b76f44636bc3391d24c5a1fe8&tradeNo=14640932403117846429&tradeStatus=PAY_SUCCESS&gmtCreate=2016-05-24 20:34:00&gmtPayment=2016-05-24 20:34:27&totalAmount=100&signType=HmacSHA256&sign=xxxxxxxxxx
//获取云支付POST过来反馈信息
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] + ",";
}
params.put(name, valueStr);
}
/**
* 验证消息是否是云支付发出的合法消息
* @param params 通知返回来的参数数组
* @return 验证结果
*/
public static boolean verify(Map<String, String> params) {
//isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
String sign = "";
if(params.get("sign") != null) {sign = params.get("sign");}
boolean isSign = getSignVeryfy(params, sign);
if (isSign) {
return true;
} else {
return false;
}
//交易号
String bizOrderNo = params.get("bizOrderNo");
//交易状态
String tradeStatus = params.get("tradeStatus");
//获取云支付的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
if(UpayNotify.verify(params)){//验证成功
//请在这里加上开发者的业务逻辑程序代码
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
if(tradeStatus.equals("PAY_SUCCESS")){
//判断该笔订单是否在开发者系统中已经做过处理
//如果没有做过处理,根据订单号(bizOrderNo)在开发者的订单系统中查到该笔订单的详细,并执行开发者的业务程序
//如果有做过处理,不执行开发者的业务程序
}
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
out.print("success"); //请不要修改或删除
}else{//验证失败
out.print("fail");
}