发奖方式选择为【奇门回调】时,需要对接该文档中的奇门发奖方式;如发奖方式选择为【小程序内回调】时,无需对接该文档,相关配置请查看广告位创建及设置。
奇门的官方集成场景,可以理解为是平台定义好接口的出入参,由三方开发者做具体实现的一种方案。
针对广告的场景,开发者需要针对每个小游戏,实现“小程序任务奖励发放”场景,点击场景后方的“进入”按钮,可以查看具体的api列表;
核心的api有两个,一个实现奖励发放,一个实现奖励退回,可以分别点击api的“开发文档”,查看对应的出入参说明。
奖励发放接口参数信息展示页如下:
奖励退回接口参数信息展示页如下:
特别注意:当收到奖励退回消息时,若开发者最终决策不进行道具退回等相关操作,也需要在success字段中返回true
根据上面的文档进行开发,开发后可以自己在本地执行测试,使用业务接收示例并往自己服务地址发送请求。
为了防止接口被人乱掉用,需要在服务端做验签的逻辑,校验请求的合法性。开发者要求使用验签算法来对请求合法性进行校验。服务端验签可以使用开放sdk提供的工具类SpiUtils,验签失败时候返回“验签失败回应示例”的内容即可,验签逻辑如下。SDK提供有java,c#,php,C,NodeJS版本,如果您不使用SDK,可以根据平台的签名算法,自己实现验签逻辑。
SDK下载:
/** * 使用该方法同时请务必要阅读该方法的源码,大致了解该方法的实现。 * * 如果验签失败则需要返回验签失败的结果,并且需要和配置对应的上,系统才认为是验签成功; * * 如果正确的请求老是误认为验签错误了,则确认以下几点: * 1编码是否UTF8 * 2密钥是否写错了,特别是沙箱和线上密钥别搞错 * 3request如果是json,xml类型(form不用理会)则确认inputstream是否被读取过了?如果需要使用body但不想改动麻烦,可以先执行验签, * 然后在验签结果中获取body(checkResult.getRequestBody()方法)来执行业务逻辑 * 4上层框架是否有做封装导致参数变更 * 如果名以上几点检查没问题,请提供加签前的最终字符串给技术支持协助排查 */ CheckResult result = SpiUtils.checkSign(request, targetAppSecret); //这里执行验签逻辑 if(!result.isSuccess()) { //如果验签失败则需要返回 验签失败的结果,并且需要和配置对应的上,系统才认为是验签成功 //按验签失败回应示例 }
如果开发者想要自己实现验签,可以参考下述签名算法逻辑,完成对应的验签实现。
该场景默认使用的签名算法:MD5(sign_method=md5),签名大体过程如下:
1)对所有API请求参数(包括公共参数和业务参数,但除去sign参数和byte[]类型的参数),根据参数名称的ASCII码表的顺序排序。如:foo:1, bar:2, foo_bar:3, foobar:4排序后的顺序是bar:2, foo:1, foo_bar:3, foobar:4。
2)将排序好的参数名和参数值拼装在一起,根据上面的示例得到的结果为:bar2foo1foo_bar3foobar4。
3)把拼装好的字符串采用utf-8编码,使用签名算法对编码后的字节流进行摘要。如果使用MD5算法,则需要在拼装的字符串前后加上app的secret后,再进行摘要,如:md5(secret+bar2foo1foo_bar3foobar4+secret);如果使用HMAC_MD5算法,则需要用app的secret初始化摘要算法后,再进行摘要,如:hmac_md5(bar2foo1foo_bar3foobar4)。
4)将摘要得到的字节流结果使用十六进制表示,如:hex("helloworld".getBytes("utf-8")) = "68656C6C6F776F726C64"
说明:MD5和HMAC_MD5都是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32个十六进制字符。
JAVA签名示例代码
public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException { // 第一步:检查参数是否已经排序 String[] keys = params.keySet().toArray(new String[0]); Arrays.sort(keys); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); if (Constants.SIGN_METHOD_MD5.equals(signMethod)) { //签名的摘要算法,可选值为:hmac,md5,hmac-sha256 query.append(secret); } for (String key : keys) { String value = params.get(key); if (StringUtils.areNotEmpty(key, value)) { query.append(key).append(value); } } // 第三步:使用MD5/HMAC加密 byte[] bytes; if (Constants.SIGN_METHOD_HMAC.equals(signMethod)) { bytes = encryptHMAC(query.toString(), secret); } else { query.append(secret); bytes = encryptMD5(query.toString()); } // 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用) //return byte2hex(bytes); } public static byte[] encryptHMAC(String data, String secret) throws IOException { byte[] bytes = null; try { SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), "HmacMD5"); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8)); } catch (GeneralSecurityException gse) { throw new IOException(gse.toString()); } return bytes; } public static byte[] encryptMD5(String data) throws IOException { return encryptMD5(data.getBytes(Constants.CHARSET_UTF8)); } public static byte[] encryptMD5(byte[] data) throws IOException { byte[] bytes = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); bytes = md.digest(data); } catch (GeneralSecurityException gse) { throw new IOException(gse.toString()); } return bytes; }
public static String byte2hex(byte[] bytes) { StringBuilder sign = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { sign.append("0"); } sign.append(hex.toUpperCase()); } return sign.toString(); }
C#签名示例代码
public static string SignTopRequest(IDictionary<string, string> parameters, string secret, string signMethod) { // 第一步:把字典按Key的字母顺序排序 IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal); IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator(); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); if (Constants.SIGN_METHOD_MD5.Equals(signMethod)) //签名的摘要算法,可选值为:hmac,md5,hmac-sha256 { query.Append(secret); } while (dem.MoveNext()) { string key = dem.Current.Key; string value = dem.Current.Value; if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value)) { query.Append(key).Append(value); } } // 第三步:使用MD5/HMAC加密 byte[] bytes; if (Constants.SIGN_METHOD_HMAC.Equals(signMethod)) { HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret)); bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); } else { query.Append(secret); MD5 md5 = MD5.Create(); bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); } // 第四步:把二进制转化为大写的十六进制 StringBuilder result = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { result.Append(bytes[i].ToString("X2")); } return result.ToString(); }
下一篇:广告位开关打开和关闭