文档说明


业务约定

三方应用接入,只能使 用阿里提供的账号体系进行登录和授权,不能提供独立账号注册功能。

 

通信约定

支付服务端支持两种通信模式,即http(https)模式和TOP模式。

 

Https通信方式:适合于支付成功后的数娱服务端回调 使用https通信方式采用RSA公私钥加解密。该方式cp需要首先在数娱TV开放平台 (http://open.aliplay.com/)填写开发者的RSA公钥信息。 数娱使用CP填写的公钥进行加签,CP 的服务端接到回调后,使用私钥进行解签;回调的原始内容为json格式,具体字段定义参照网络支付接口-服务端支付成功后回调通知章节。 根据原始内容json串以及RSA公钥加密后的内容encryptedData会在http参数的data字段中供CP利用 RSA私钥解密后使用

 

TOP通信方式:适合于CP主动调用支付服务的场景(如查询订单状态等) 通过TOP通信方式,该方式CP需使用数娱TV开放平台(http://open.aliplay.com/)入住时颁发的 appkey和appsecret(该信息可以在阿里TV开放平台应用管理页面中查看), TOP接口的调用请参 考//open.taobao.com/doc2/detail.htm? spm=a219a.7629140.0.0.jlQptD&treeId=49&articleId=101617&docType=1

 

安全规范

为了防止双方约定的接口(服务端 )被滥用带来的不必要的安全风险,接入的合作方需要符合以下要求做好安全控制。 如有疑问,可加入旺旺群621730614 咨询。

 

1. 接口安全规范

1)接口以HTTP方式开放。

2)设计接口需要有身份认证,对来源授权,只允许授权的IP访问.

3)所有的接口调用都需要有日志记录 密钥的传递及保存 双方约定的密钥,不应该大范围邮件传递,应以开发人员人对 人传递。密钥需要妥善保存,避免泄露密钥引起的安全隐患。

 

2 密钥及appsecret的传递及保存

接入合作方所持有的敏感信息,不应该大范围邮件传递,应以开发人员人对人传递。私钥和appsecret需要妥善保存,避免泄露私钥引起的安全隐患。

 

 

    技术示例

     

    1. RSA秘钥生成方式

    RSA是一种可用于进行签名的非对称算法,即签名密钥(私钥)与验签名密钥( 公钥)是不一样的,私钥用于签名,公钥用于验签名。使用这种算法签名在起到防数据篡改功能的 同时,还可以起到防抵赖的作用,因为私钥只有签名者知道。 可以使用Openssl RSA密钥生成工具 ,生成一套RSA公私钥。

    RSA密钥生成命令:
     
     生成 RSA私钥

     openssl genrsa -out rsa_private_key.pem 1024


     生成 RSA公钥

     openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

     将RSA私钥转换成PKCS8格式
     
     openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    该工具生成的密钥文件,里面有一些注释和回车换行,需要将其去掉后组成一串字符!

     

    2. RSA签名(sign)算法示例

     

    Java参考代码

     

    /**

        * RSA签名算法

        * @param privateKey

        * @param content

        * @param charset

        * @return

        * @throws Exception

        */

       public static String sign(String privateKey, String content, String charset) throws Exception {

          PKCS8EncodedKeySpec priPKCS8   = new PKCS8EncodedKeySpec( Base64.decodeBase64(privateKey) );

          KeyFactory keyf = KeyFactory.getInstance("RSA");

          PrivateKey priKey = keyf.generatePrivate(priPKCS8);

           

          java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");

          signature.initSign(priKey);

          signature.update(content.getBytes(charset) );

          byte[] signed = signature.sign();

          return Base64.encodeBase64String(signed);

       }

     

     

    PHP参考代码

     

    $privkey = file_get_contents("rsa_private_key.pem"); //无需转PKCS8$privkey = file_get_contents("rsa_private_key.pem"); //无需转PKCS8

    $res = openssl_get_privatekey($privkey);

    openssl_sign($data, $sign, $res);

    $sign = base64_encode($sign);

    $res = openssl_get_privatekey($privkey);

    openssl_sign($data, $sign, $res);

    $sign = base64_encode($sign);

     

     

    3. 服务端notify解密demo(java版)

     

    package testRsa;

    import java.io.ByteArrayInputStream;

    import java.io.ByteArrayOutputStream;

    import java.io.InputStream;

    import java.io.UnsupportedEncodingException;

    import java.security.InvalidKeyException;

    import java.security.KeyFactory;

    import java.security.NoSuchAlgorithmException;

    import java.security.PrivateKey;

    import java.security.SignatureException;

    import java.security.spec.InvalidKeySpecException;

    import java.security.spec.PKCS8EncodedKeySpec;

    import javax.crypto.Cipher;

    import org.apache.commons.codec.binary.Base64;

    /**

     *

     * @author zhiyong.xiongzy

     *

    🎜 */🎜🎜public class testRSA {🎜

          私有静态字符串prikey          =“MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMhDP5oVLHPJpM0QDuAGPupAkF4N3bMOD252BIYncKd8ppYJP0sA1wxnJxrVJN6UOzgK2qEReH UCzda5Hj+GaR8dmYz3v4UMozNeXhx7iqI7EK4Myp/qjCV2ROgh2LaL1ycugacTVx6dSfFvIOcczyhs8D4B UiJlSMsTWPVCSKsPAgMBAAECgYEAkL5KUgvLvUSZIL3ignkBMD7KGbDb9HbNIIGcc3o+KlAl93tni8ZnqEd GNFap91YcFz2BF7mQ3sHQFMpn2nJDtzj0tPsCKtNLHmpOi0ctAxedhzip+rOT6obNK+POL6czMWGJOaW8zLefxftgZWkT+eZactn507xc+GiwNsodAMECQQD4OjjnMhQWaSv8kHI27pH92PTv4zFb1 MSB0H65Im2zQ+8JrlqEH/7AqqMIxkPjIMC/vJLpkZG4TYMCYXjd4rx7AkEAzoiLGwUsXDApbDJJxxgYV6y50H/oJm6ooIOHoCwrluJhlOD81oUQyrLGfgNL95v4avvuQezZ4kmkeWDPvQ35fQJACBM8zqi eZqw9NhYs4QSZ0zw/m540eNxc1s5FkRhBoVdQa2w0nZ+81d+3Ng3dH4JtQs+Lp/WIXAqJfIZXPECoCQJAW8QBgrTuu9toXFuPul1zW2lMel6KiKD8Xa1zUnCtwXG+h8bbsHkZN+b tGMpgM5libC6Z80LIoKm14ZRpWQffhQJBAJyxWEnzZA9dvqEhj6I/BTPJgvzc/boGzZ2lKQlN8j57MDkZHryoWtoKjB3Hp5dvTasweI6WHtIm313TSLuoXrg=" ;

          public static void main(String[] args) {

                字符串内容 = "c/BOhNHjhvCXvOenIyNqmr0FI1M3cYt/BR/WEoMgoi37ZFvKe418xOlRU4AN/QyvY2H7g2osL9oLMArsw35j k43reMFUyemTLnZ4Xw/DXT5xxPzHy4NWLt2/K0mqA2e5PiShf8RX9EdLnoIYZPXKe3Ldnw0ha3RZtP4X2tBsHqU=";

                 字符串 jsonStr;

           尝试 {

            //解密

                 jsonStr =解密(content, prikey, "UTF-8");

                 System.out.println(jsonStr);

                 //签名签名

                 System.out.print ln(符号(prikey,内容,“UTF -8"));

           } catch (异常 e) {

                 e.printStackTrace();

           }

                 

          }

          

          /**

           * RSA签名算法

           * @param privateKey

           * @param content

           * @param charset

           * @return

           * @throws Exception

           */

          public static String sign(String privateKey, String content, String charset) throws Exception {

                PKCS8EncodedKeySpec priPKCS8   = new PKCS8EncodedKeySpec( Base64.decodeBase64(privateKey) );

                 KeyFactory keyf = KeyFactory.getInstance("RSA");

    PrivateKey priKey = keyf.generatePrivate(priPKCS8);

                  

                 java.security.Signature 签名 = java.security.Signature.getInstance("SHA1WithRSA");

                 signature.initSign(priKey);

                 signature.update(内容.getBytes(charset) );

                 byte[]signed = signature.sign();

                 return Base64.encodeBase64String(signed);

          }

     

          公共静态字符串解密(字符串内容、字符串 private_key、字符串 input_charset ) 抛出异常 {

                 

                 

                 PrivateKey prikey = getPrivateKey(private_key);

                 Cipher cipher = Cipher.getInstance( "RSA");

                 cipher.init(Cipher.DECRYPT_MODE, prikey);

                 InputStream ins = new ByteArrayInputStream(Base64.decodeBase64(content.getBytes()));

                 ByteArrayOutputStream writer = new ByteArrayOutputStream();

                 //rsa解密的字节最多为128,将需要解密的内容的大小,按128位拆开解密

                 byte[] buf = new byte[128];

                 int bufl;

                 while ((bufl = ins.read(buf)) != -1) {

                        byte[] block = null;

                       if (buf.length == bufl) {

                               block = buf;

                        } else {

                               block = new byte[bufl];

                                for (int i = 0; i < bufl; i++) {

                                    块[i] = buf[i];

                              }

                        }

                        writer.write(cipher.doFinal(block));

                 }

                  返回新字符串(writer .toByteArray(), input_charset);

          }

     

          public static PrivateKey getPrivateKey(String key) 抛出异常 {

                 byte[] keyBytes;

                 keyBytes = Base64.decodeBase64(key.getBytes());

    //使用PKCS8  

                 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

                 KeyFactory keyFactory = KeyFactory.getInstance("RSA");

                 return privateKey ;

          }

     

    }

                 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);


     

     

    4. 服务端通知demo(php版)


    $privkey=<< ;<EOT

    -----开始私钥-----

    MIICdwiBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN/dCMqrU4GCvJ1s

    QwPxvCnYSsXsm0+wdIzPBajdRiI9 rvgtxRDq10yHG wXs+RNOGxaglj0F+9kRQ7l5

    BEkN/HgPg90uWT6bNp5Qf4K3qJ WfY6FmWoNDKYyIYjDacAVheAC/Idg/0nKgTUKH

    sowx8iXHnKBB3o7B7XGoKCjF Kc2PAgMBAAECgYEAJIVA qYdVyav5HZABmQ46oMGm

    XGSHIQOM3URSLW0EOWU5MWV38ACILOOO9T5RBVYORCUH3HCNK6VGZ6SAHQYLK/MKK8

    HYNSBNAWH5/XZUUUI7ZQQQQQQW5NFOLIHGDKXCNZGHP5KGHP5KGHP5A6ETGXBIESSSSCNERSSSCNERSSCLIHEN +2 QQD4EVHSYZKMMFAPNJPWCGULPL7HZ1FTE5N83S IZHY/

    6WJSC0FPKICMPXRGHL2YM3GP0KS4B7/uuulieqypoawdakea5qthzl/ Emnuxd5HO1VZ3RNIVRVRX

    Sysugwjacv9x2olbnoimkorprcun1pv375KX9DUS3ITQTJPZQOFQ+rk0sbng51d1d1d

    oz3f3lynvi/dmwar9dlgppijabal4 WFX

    P/L3DF7VENV6MPMCKYEJQ8TOBGOG234KXGSF0KYTZHPNCZPRY8WJQE0CQCCNV7TH8TH8

    jnlWQ21UVBL1Lr3KcMM/0RJ0hiVGH46Gp93h9c2zs AgHQ01HLi1BeRcM1tZZNPIh

    GqEuuIa /iXjzNNc=

    -----END私钥-----

    EOT;

    $res = openssl_get _privatekey($privkey);

    //$content = "ycoYI7SXtj9GWHNS27jeF18x7B0JVFxyb0+ X/K4FJH PE7JVWK7TGDT5VF +NWJBKPPVFYV5NRUYMNRHSHSHSHSEQGD4AWO6Y3E3E5HWGMHCA92YDAZRISQRISQRISQRISQU2FAUD4 + KNQW9AHJVOAMYHY2 6Z11IHM771DFA + 4W2TAEALHOEZHCE1W8UBXZPMLXLKT666HOHVQXZRF88G ====“

    $ content = $ content = $ _post ['data'''' 0 ;

    $result = "";

    while

    ($head = substr($content, $i, 128)) {

          $i += 128;

          openssl_private_decrypt($head,$newsource,$

    SDK接入1)AlitvSDKLib包含了SD K占用的lib和res

    2)AlitvSDKDemo引用上述Lib工程

     

    2

    按照以下截图配置,将SDK导入您的工程

    1)  在项目属性中配置

            2.jpg


     

    2) 在Java Build Path中配置

    3.jpg

    3)配置manifest可合并

              在您的工程根目录中的project.properties里加入一行代码: manifestmerger.enabled=true