拼者积分商城以h5页面为载体。客户app只要将获取到的url嵌入到自身app产品页面中即可,手机端用户可以免登录URL进入积分商城,兑换礼品同步扣除积分,同时积分商城给用户兑换结果推送到客户系统后台。
接入拼者积分商城主要分三部分来完成,主要包括
账号注册#
在对接拼者积分商城之前,开发者需要先注册拼者积分账号,并获取分配的应用唯一标识
appKey
和密钥appSecret
。接口对接#
开发者把拼者积分商城集成到自己的
app
、小程序
或者微信公众号
中,需要对接拼者积分相关接口。接口配置和上线使用#
接口开发完成以后,需要把接口地址配置到拼者积分后台的接口配置页面。
术语定义
术语名称 | 说明 |
---|---|
开发者 | 使用拼者积分商城服务的开发者简称。 |
积分 | 开发者与拼者积分商城对接使用的虚拟货币单位 ,开发者可以自己更改货币名称 和 货币汇率 。 |
汇率 | 开发者自己平台上的虚拟货币与现实中人民币的大致比率。如:100积分 = 1元 意味着100积分 可以兑换1元 面值的商品。 |
服务端 | 指开发者的服务器,用于接口对接。 |
客户端 | 又称用户端,纯 H5 方式接入。 |
自动登录url | 又称免登录 url ,在用户进入拼者积分商城的时候由服务端实时生成,提供用户的登录信息,包含用户 id 和积分值。 |
扣积分接口 | 用户发起兑换请求后,拼者积分会向开发者发一个扣积分的 http 请求,开发者接收到请求后,需创建订单、扣除用户相应的积分,并响应相应的信息。 |
通知接口 | 用户在拼者积分兑换成功/失败 后,拼者积分会向开发者发通知请求,告知订单最终结果,开发者需根据通知结果修改本地订单状态 ,如果结果为失败 ,还需要退还用户之前扣除的积分。 |
开发者账号 | 开发者在拼者积分注册的账号。 |
应用(app) | 开发者账号下可以创建多个应用,便于统一账号下管理。 |
appKey | 每个应用都有一个唯一的标识码。 |
签名 | 遍历请求参数的值进行 MD5 编码,比对 sign 值,确保请求不可伪造。 |
channel | 应用的渠道标识(游戏类应用)。 |
————对接基础接口:—————
1、免登录URL接口
1.1积分商城本质上是一个 H5 网页,客户app需要将网页嵌入到 app 中去。
1.2、用户登录积分商城商城,需要客户app根据用户信息在服务端生成一个免登录 url,通过这个 url 链接,积分商城才能知道是哪个用户来访问,并通过 credits 参数获取用户的积分余额。
1.3、为了确保客户端每次请求到都是最新的免登录 url,客户端每次向服务器发的请求不能是固定的,以避免请求被缓存。
1.4、积分商城免登录 url 经过签名,该 url 地址 5分钟 失效,请务必在生成地址后立即使用,使用后用户即可进入积分商城,登录状态 24小时 有效。
1.5、客户app服务器端需要通过一个重定向功能实现动态生成免登录 url 地址。
1.6、如果客户app事先生成免登录 url 地址,将导致 5分钟 后用户访问该地址过期
接口地址#
https://v.pinzz.cn/pinzz_creditmall/api.php
API 参数#
参数 | 是否必须 | 类型 | 长度限制 | 说明 |
---|---|---|---|---|
uid | yes | string | 128 | 用户id |
credits | yes | long | 20 | 用户积分余额 |
appKey | yes | string | 32 | 接口appKey ,应用的唯一标识 |
timeStamp | yes | long | 20 | 1970-01-01 开始的时间戳,秒为单位 |
sign | yes | string | 32 | MD5 签名,详见 签名规则 |
channel | no | string | 255 | 渠道标识符(仅针对游戏类别应用) |
goodsId | no | int | 255 | 商品ID,若传入则直接跳转至商品详情页 |
isJumpRecord | no | int | 1 | 是否跳转至兑换记录页,0:不跳转,1:跳转 |
isHiddenNavBar | no | int | 1 | 是否隐藏导航栏,0:不隐藏,1:隐藏 |
nickname | no | string | 20 | 用户昵称 |
wxOpenId | no | string | 128 | 用户微信标识,接入小程序支付时必须传此字段 |
redirectType | no | string | 128 | 跳转类型,(商品详情:goods,商品分类:goodsClassify,限量抢兑列表:limitActivity,积分夺宝:lotteryDraw,积分夺宝列表:lotteryDrawList,抽奖游戏:gameActivity,订单列表:orderList,拼团列表:teamList,拼团详情:teamDetails) |
redirectPageId | no | int | 11 | 跳转页面ID(跳转商品详情、积分夺宝、抽奖游戏、拼团详情时必填) |
请求示例#
https://v.pinzz.cn/pinzz_creditmall/api.php?appKey=Fii6DgbvqWnEm2HYXupl5oaw&channel=17173&credits=200000&timeStamp=1459161352&uid=neo&sign=b451fb67aa4996d2c08b3567ba3591d3
Java 代码示例#
package com.mailejifen.sign;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;import java.util.Map;public class Sign { public static void main(String[] args) { //生成自动登录URL,用户根据自己需要更改HashMap中的数据 HashMap<String, String> params = new HashMap<String, String>(); params.put("uid", "商户登录用户标识"); params.put("appKey", "商户对应的appKey(由拼者积分商城提供)"); params.put("credits", "商户登录用户当前积分"); params.put("channel", "商户提供的渠道标识符(仅针对游戏类应用)"); params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));//当前时间戳 params.put("sign", buildSign(params, "商户对应的appSercet(由拼者积分商城提供)")); String query = httpBuildQuery(params); String url = "https://v.pinzz.cn/pinzz_creditmall/api.php?" + query; System.out.println(url); } /** * 获得签名值 * * @param params 传递给URL的参数,不含sign * @param secret App对应的secret * @return string */ public static String buildSign(HashMap<String, String> params, String secret) { Object[] keys = params.keySet().toArray(); Arrays.sort(keys); String str = ""; for (Object key : keys) { str += params.get(key); } str += secret; //MD5生成方法有许多种,如有需要可网上查一下,在此就不再贴MD5类的源码了 String sign = MD5.getMD5Code(str); return sign; } /** * 生成query * * @param params 传递给URL的参数,含sign * @return string */ public static String httpBuildQuery(HashMap<String, String> params) { String query = ""; Iterator iter = params.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); query += entry.getKey() + "=" + entry.getValue() + "&"; } return query; }}
PHP 代码示例#
$appSercet = ''; //商户对应的appSercet(由拼者积分商城提供) $appKey = ''; //商户对应的appKey(由拼者积分商城提供) $uid = ''; //商户登录用户标识 $timeStamp = time();//当前时间戳 $credits = 1000; //商户登录用户当前积分 $channel = ''; //商户提供的渠道标识符(仅针对游戏类应用) $string = ''; //预定义构造请求url $params = array( 'uid'=> $uid, 'appKey' => $appKey, 'timeStamp' => $timeStamp, 'credits' => $credits, 'channel' => $channel ); ksort($params); $string = join("", $params); $params['sign'] = md5($string . $appSercet); $query = http_build_query($params); return "https://v.pinzz.cn/pinzz_creditmall/api.php?" . $query;
2、用户积分扣除接口
2.1当用户发起兑换请求后,积分商城将会创建一个订单,然后发起该用户的积分扣除请求给客户app。
2.2这个请求会包含用户 id,积分商城订单号,消耗的积分数,兑换类型等等信息。客户app收到该请求后,请自行在系统中创建订单,并记录请求中的相关信息,同时执行用户积分扣除行为。
2.3如果扣除成功,写入成功的参数和客户app系统的订单号,返回这个响应给积分商城。
2.4如果扣除失败,写入失败的参数,并带上失败原因。积分商城收到失败响应后会将这个兑换订单标记为失败,并转告用户失败原因。
2.5扣积分行为可能会发生超时的情况,对于这种情况,积分商城会将订单标记为失败,并进行失败通知。
后台配置方法#
扣积分超时处理方式#
拼者积分向开发者发起扣积分请求时,拼者积分设置超时时间为
30秒
,由于开发者服务器响应过慢,或者网络异常等原因,可能会出现超时情况。针对超时情况,拼者积分将该订单标记为失败,并向开发者发出失败通知。 如果开发者已经扣积分成功了,当收到通知时,需要对用户积分进行回滚。
因为扣积分请求超时,拼者积分并没有收到开发者的订单号,因此在发送失败通知时,不会携带
bizId
数据。开发者在接受拼者积分通知时,请以拼者积分订单号
orderSn
进行处理,而不要根据bizId
进行处理!
API 参数#
参数 | 是否必须 | 类型 | 限制长度 | 说明 |
---|---|---|---|---|
uid | yes | string | 255 | 用户id |
credits | yes | long | 20 | 本次兑换扣除的积分,当领取活动奖品时该值为0 |
appKey | yes | string | 255 | 接口appKey ,应用的唯一标识 |
timeStamp | yes | string | 20 | 1970-01-01 开始的时间戳,秒为单位 |
description | no | string | 255 | 本次积分消耗的描述(带中文,请用utf-8 进行url 解码) |
orderSn | yes | string | 255 | 拼者积分订单号(请记录到数据库中) |
type | yes | string | 255 | 兑换类型(reality:实物 ,phonefees:话费 ,phonetraffic:流量 ,coupon:卡券 ,activity:活动 ) |
facePrice | no | int | 11 | 兑换商品的市场价值,单位是分,请自行转换单位 |
actualPrice | yes | int | 11 | 此次兑换实际扣除开发者账户费用,单位为分 |
ip | no | string | 255 | 用户ip,不保证获取到 |
token | no | string | 255 | 用于校验本次下单的支付密码是否合法,请查看 支付密码示例页面 |
orderParams | no | string | 255 | 详情参数,不同的类型,返回不同的内容(json 格式的字符串,通过解码成json 对象读取数据),实物类型返回字段包含字段:phone,addressee,address ;手机充值类型包含字段:phone |
sign | yes | string | 255 | MD5 签名,详见 签名规则 |
响应参数#
参数 | 是否必须 | 类型 | 限制长度 | 说明 |
---|---|---|---|---|
code | yes | int | 状态码,0 :处理成功,其他状态则判定为处理失败 | |
msg | yes | string | 255 | 出错原因 |
data | yes | 返回数据 | ||
bizId | no | string | 255 | 开发者的订单号(拼者积分会判断该订单号的唯一性,注意区分测试和正式对接时的订单号,以免重复) |
credits | yes | long | 20 | 用户积分余额 |
响应示例#
{ "code": 0, "data": { "bizId": "1023851231", "credits": 185 }}
注:请以标准
json
格式返回,字段名、字符串变量必须加双引号,数字类型不能用引号包含,对象、数组的最后一个元素不能有逗号结尾
3、用户兑换结果通知接口
3.1不管兑换行为最终成功还是失败,积分商城都会向客户app发出通知,汇报兑换结果。
3.2客户app收到通知后,请以积分商城订单号 orderSn 为准进行处理,不要以客户app订单号bizId进行处理。原因详见上一章节的:扣积分超时处理方式。
3.3如果兑换成功,客户app在系统内标记此订单为成功状态即可。如果兑换失败,客户app需要将该订单标记为失败,并将之前预扣的积分或余额返还给用户。
3.4无论接收到的结果如何,只要客户app收到该请求,请返回JSON格式的code=0,否则积分商城将进行重复通知,直到客户app收到或者24小时内最多重复 4次
后台配置方法#
扣积分超时处理方式#
拼者积分向开发者发起扣积分请求时,拼者积分设置超时时间为
30秒
,由于开发者服务器响应过慢,或者网络异常等原因,可能会出现超时情况。针对超时情况,拼者积分将该订单标记为失败,并向开发者发出失败通知。 如果开发者已经扣积分成功了,当收到通知时,需要对用户积分进行回滚。
因为扣积分请求超时,拼者积分并没有收到开发者的订单号,因此在发送失败通知时,不会携带
bizId
数据。开发者在接受拼者积分通知时,请以麦乐积分订单号
orderSn
进行处理,而不要根据bizId
进行处理!
API参数#
参数 | 是否必须 | 类型 | 限制长度 | 说明 |
---|---|---|---|---|
appKey | yes | string | 255 | 接口appKey ,应用的唯一标识码 |
timeStamp | yes | long | 20 | 1970-01-01 开始的时间戳,秒为单位 |
success | yes | int | 1 | 0 表示失败,1 表示成功 |
errorMessage | no | string | 255 | 出错原因(带中文,请用utf-8 进行解码) |
orderSn | yes | string | 255 | 拼者积分订单号 |
type | yes | string | 255 | 兑换类型 |
bizId | no | string | 255 | 开发者的订单号 |
uid | no | string | 128 | 用户id |
sign | yes | string | 255 | 签名,详见 签名规则 |
响应参数:#
{ "code": 0}
开发者服务器端收到通知并处理完成后,请返回
JSON
格式的code=0
,拼者积分在验证到响应为JSON
格式的code=0
后会标记通知成功。如果响应为非以上结果,拼者积分会在
24小时
内最多重试4次
通知。 通知时间间隔为:1m、2m、10m、1h
。
注:出于网络异常的可能性,拼者积分可能会对开发者进行重复通知,开发者务必确保一笔订单不进行重复处理,否则将产生严重
bug
;详细原因参考下述:重复通知处理
重复通知处理#
由于网络具有不稳定的特性,当拼者积分向开发者服务器发送成功/失败通知时,有可能存在拼者积分发送了通知,开发者收到了通知并进行了处理。
若此时出现网络故障,开发者响应拼者积分失败,拼者积分没有收到开发者的响应,拼者积分会认为开发者没有收到通知,于是进行重复通知。
此时开发者收到通知后,务必先确认此订单是否已经处理过。如果已经处理过,则忽略此通知,并响应
JSON
格式的code=0
。如果此时开发者忽略订单是否已经被处理过,而直接进行处理,将导致开发者反复向用户返还积分,导致损失!
注:有部分订单如实物类订单,需等待发货之后才会确认订单成功,此类订单可能会隔比较长时间才发订单结果通知;如果限制了通知等待时长会导致部分订单接收不到结果。
积分接口说明#
当用户发起查看积分请求后,拼者积分将会调用该接口查看积分明细,商户返回对应的积分明细。
这个请求会包含用户 id,消费类型等等信息。开发者收到该请求后,返回对应用户的积分明细。
如果查询失败,写入失败的参数,并带上失败原因。拼者积分收到失败响应后会转告用户失败原因。
API 参数#
参数 | 是否必须 | 类型 | 限制长度 | 说明 |
---|---|---|---|---|
uid | yes | string | 255 | 用户id |
credits_type | yes | int | 4 | 积分类型(0:全部,1:积分收入,2:积分消耗) |
appKey | yes | string | 255 | 接口appKey ,应用的唯一标识 |
timeStamp | yes | string | 20 | 1970-01-01 开始的时间戳,秒为单位 |
page | yes | int | 11 | 当前页数 |
pageSize | yes | 11 | 11 | 每页多少条数据 |
sign | yes | string | 255 | MD5 签名,详见 签名规则 |
响应参数#
参数 | 是否必须 | 类型 | 限制长度 | 说明 |
---|---|---|---|---|
id | yes | 数据id | ||
active_name | yes | string | 255 | 事件名称(例如:抽奖、签到) |
credits_amount | yes | int | 积分值 | |
create_time | yes | 事件时间 | ||
credits_type | yes | int | 4 | 积分类型(1:积分收入 2:积分消耗) |
响应示例#
{ "code": 0, "msg":"", "data": [ { "id": 1, "active_name": "抽奖", "credits_amount": 10, "create_time": "2020-5-19", "credits_type": 2 }, { "id": 2, "active_name": "签到", "credits_amount": 10, "create_time": "2020-5-19", "credits_type": 1 } ]}
注:请以标准
json
格式返回,字段名、字符串变量必须加双引号,数字类型不能用引号包含,对象、数组的最后一个元素不能有逗号结尾
11月3日中国银行招标需要给客户解答技术上几点问题:
1、我们的平台如何和客户的手机端口对接,需要客户提供哪些数据或者开放什么样的端口
答:我们积分商城通过h5网页链接到客户app,需要客户app在服务端生成一个免登录 url,我们积分商城才能知道是哪个用户来访问,并通过 credits 参数获取用户的积分余额。
2、按照我们以往的技术,对接过程中会有哪些BUG,我们如何快速解决
答:会出现以下错误情况:
a.请求已过期:为了安全免登陆地址是有5分钟的有效期的
出错的免登录链接地址,观察链接中时间戳的参数(timestamp)的值是
b签名验证失败
检查验签的appkey和appsecrect是否和请求一致
3、对接打通后,呈现方式有几种,弹窗、植入、还有哪些?
答:植入h5网页的方式
4、从客户给到对接端口数据到接通,需要多久,之前有无成功案例可与客户分享
答:需要15天技术开发