OPPO开放平台快应用支付服务文档

2018-06-25 20:19 更新

一、客户端支付接口


接口声明
{"name": "service.pay"}

导入模块

import pay from '@service.pay' 或 const pay = require('@service.pay')

接口定义 

pay.getProvider() 

获取服务提供商 

参数: 

无 

返回值: 

字符串,服务提供商的代号,如厂商的英文品牌名称,若无此服务则返回空字符串 

示例: 

console.log(pay.getProvider())


pay.pay(object) 

使用支付完成付款 

参数: 

参数名

类型

必填

说明

orderInfo

Json

订单信息

success

Function

成功回调

fail

Funtion

失败回调

complete

Function

执行结束后的回调


orderInfo支持的key:

参数名

类型

必填

说明

cpOrderId

String

订单号,不超过100个字符,一般由服务端生成

productName

String

商品名称,不超过40个字符

productDesc

String

商品描述,不超过120个字符

callBackUrl

String

回调链接

price

String

商品价格,以分为单位,最大值999999

appKey

String

快应用的appkey(在开放平台获取)

appId

String

快应用的appid(在开放平台获取)

timestamp

String

时间戳

sign

String

签名

attach

String

附加信息


签名规则:

要求:出于安全性的考虑,签名应由服务端生成给到快应用客户端,再由客户端调起支付。

签名算法: 

1)构造源串 

* 将支付参数中需要参与签名的参数(参见下表),按参数名的ASCII码的增序排序,若遇到相同首字母,则看第二个字母,以此类推。 拼接后的源串格式为a=xxxxxx&b=xxxxxxx&c=xxxxxxxxxxx... 

* 参数表:

参数名

描述

appId

应用id

cpOrderId

订单号

callBackUrl

回调地址

productName

产品名称

price

产品价格

timestamp

时间戳


2)生成签名值

* 将源串使用RSA算法(SHA256WithRSA),用私钥进行签名

* 将签名后的字符数组经过Base64编码,生成签名值

3)代码示例

public class Example {
    
    private static final Logger logger = LoggerFactory.getLogger(Example.class);
    
    public static String getSignContent() {
        
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("appId", "123456");
        treeMap.put("cpOrderId", "abcde");
        treeMap.put("callBackUrl", "http://xxx.aa.bb");
        treeMap.put("productName", "游戏点卡");
        treeMap.put("price", String.valueOf(200));
        treeMap.put("timestamp", "233123123131");
        
        Set<String> keys = treeMap.keySet();
        StringBuilder sb = new StringBuilder();
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            sb.append(key).append("=").append(treeMap.get(key)).append("&");
        }
        
        String signContent = sb.toString().substring(0, sb.length() - 1);
        
        return signContent;
        
    }
    
    public static String sign(String content, String privateKey) {
        String charset = "utf-8";
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.base64Decode(privateKey));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance("SHA256WithRSA");
            
            signature.initSign(priKey);
            signature.update(content.getBytes(charset));
            
            byte[] signed = signature.sign();
            
            return Base64.base64Encode(signed);
        } catch (Exception e) {
            logger.error("签名出错.", e);
        }
        
        return null;
    }
    
    public static void main(String[] args) {
        String signContent = getSignContent();
        String priKey = "abcdefghijk";
        String sign = sign(signContent, priKey);
        System.out.println(sign);
    }
}

success返回值

参数名

类型

说明

code

Integer

返回状态码

message

String

消息内容

result

String

支付结果


fail返回值

参数名

类型

说明

code

Integer

返回状态码

message

String

消息内容


失败code定义

返回码

描述

200

参数不合法,在message字段中可拿到详细信息

1002

订单号重复

1003

超过最大限额

10040

通知支付发起者支付app 需要安装或者更新

1005

结果未知

1007

版本无更新

1010

支付失败

1012

正在处理中

1100

未知错误

1200

签名错误

1201

缺少参数

5000

金额错误

5001

系统错误

5002

余额不足

5003

参数异常

5004

用户不存在

5005

登录鉴权失败

5006

商户订单号重复

5555

支付失败

6001

换订单失败

6002

获取Token失败

6003

订单号不匹配


代码示例:

pay.pay({
  orderInfo: {
          'cpOrderId': 'your orderid',
          'productName': 'iWatch',
          'productDesc': '42mm',
          'callBackUrl': 'your callback url',
          'price': 1,
          'appKey': 'your appkey',
          'appId': 'your appid',
          'timestamp': (new Date()).getTime(),
          'sign': 'sign'
	'attach': '',
        }
  success: function (data) {
    console.log(`handling success: ${data.code}`)
  },
  fail: function (data, code) {
    console.log(`handling fail, code = ${code}`)
  }
})

二、支付成功服务端回调


用户支付成功后,快应用平台会根据快应用在调用支付接口时提供的回调地址进行回调。 


回调参数: 

服务端在回调时,会传递以下参数给cp服务端,建议cp服务端对订单的字段进行校验。

字段名

字段描述

是否参与签名

notifyId

通知id

Y

partnerOrder

订单ID

Y

productName

商品名称

Y

productDesc

商品描述

Y

price

商品价格

Y

count

商品数量

Y

attach

附件

Y

sign

签名,由平台用私钥签名,cp服务端需要使用平台给cp分配的公钥进行验签



签名算法:

1) 构建源串:将支付参数中需要参与签名的参数,按参数名的ASCII码的增序排序,若遇到相同首字母,则看第二个字母,以此类推。 拼接后的源串格式为a=xxx&b=xxx&c=xxx

2) 将源串使用RSA算法(SHA256WithRSA),用私钥进行签名,将签名后的字符数组经过Base64编码,生成签名值。

3) 示例代码:

/**
* 签名
*/
public static String signForCallBackCp(String priKey) {
      
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("notifyId", "notifyId");
        treeMap.put("partnerOrder", "partnerOrder");
        treeMap.put("productName", "productName");
        treeMap.put("productDesc", "productDesc");
        treeMap.put("price", String.valueOf("100"));
        treeMap.put("count",
            String.valueOf(1));
        treeMap.put("attach", "");
        
        Set<String> keys = treeMap.keySet();
        StringBuilder sb = new StringBuilder();
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            sb.append(key).append("=").append(treeMap.get(key)).append("&");
        }
        
        String signContent = sb.toString().substring(0, sb.length() - 1);
        
        String sign = RsaUtil.sign(signContent, priKey, "SHA256WithRSA");
        
        logger.info(" signForCallBackCp source:{}  sign:{}", signContent, sign);
        
        return sign;
        
    }


public static String sign(String content, String privateKey, String signAlgorithm) {
        
        String charset = "utf-8";
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.base64Decode(privateKey));
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance(signAlgorithm);
            
            signature.initSign(priKey);
            signature.update(content.getBytes(charset));
            
            byte[] signed = signature.sign();
            
            return Base64.base64Encode(signed);
        } catch (Exception e) {
            logger.error("签名出错.", e);
        }
        
        return null;
    }

响应结果: 

1)cp服务端如果对回调响应成功,需要返回“ok”字符串,如果处理失败,请返回非“ok”字符串。 

2)快应用平台如果接收到响应结果为“ok”字符串,则认为回调成功,这个支付流程结束。如果接收到的结果为非“ok”字符串或回调异常则会进行重试,最大回调重试次数为28次。




以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号