API通过电话发送验证码,然后用户进入网站...基本上验证电话号码是否有效。
但我在签署请求时遇到问题。无论我尝试什么,它都会返回“无效签名”
API文档: http://docs.telesign.com/rest/content/verify-call.html
身份验证文档: http://docs.telesign.com/rest/content/rest-auth.html
身份验证示例: http://docs.telesign.com/rest/content/auth-examples.html
代码:
<cffunction name="encryptHmacSHA1" returntype="binary" access="public" output="false">
<cfargument name="base64Key" type="string" required="true">
<cfargument name="signMessage" type="string" required="true">
<cfargument name="encoding" type="string" default="UTF-8">
<cfset var messageBytes = JavaCast("string",arguments.signMessage).getBytes(arguments.encoding)>
<cfset var keyBytes = binaryDecode(arguments.base64Key, "base64")>
<cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec")>
<cfset var mac = createObject("java","javax.crypto.Mac")>
<cfset key = key.init(keyBytes,"HmacSHA1")>
<cfset mac = mac.getInstance(key.getAlgorithm())>
<cfset mac.init(key)>
<cfset mac.update(messageBytes)>
<cfreturn mac.doFinal()>
</cffunction>
<cfscript>
// PHONE NUMBER TO CALL
phoneNumberToCall = "15554565555";
// KEYS
keys = structNew();
keys.customerID = "D561FCF4-BA8D-4DFC-86D1-1A46DF47A308";
keys.apiKey = "mDzGHsMOc2g/ivkuINEFVh6fn/v4kdjvlTvtgFVOShu7hVWXS0eV2nLSw1FXgEzDSuOjhlKLXvneiq+YFG1/Vg==";
// DATES
dates = structNew();
dates.timeZoneInfo = GetTimeZoneInfo();
dates.dateToUse = DateAdd("h",dates.timeZoneInfo.utcHourOffset,now());
dates.signingDate = DateFormat(dates.dateToUse,"ddd, dd mmm yyyy") & " " & TimeFormat(dates.dateToUse,"HH:mm:ss") & " +0000";
// HEADERS
headers = [
"POST",
"application/x-www-form-urlencoded",
"#dates.signingDate#",
"phone_number=#phoneNumberToCall#&ucid=OTHR",
"/v1/verify/call"
];
headerText = arrayToList(headers, chr(10)) & chr(10);
// CREATE SIGNATURE
stringToSign = binaryEncode( encryptHmacSHA1(keys.apiKey, headerText), "base64");
// AUTHORIZE HEADER
Authorization = "TSA" & " " & keys.customerID & ":" & stringToSign;
</cfscript>
<cfhttp method="POST" url="https://rest.telesign.com/v1/verify/call" port="443" charset="UTF-8" result="verifyPhoneCall">
<cfhttpparam type="header" name="authorization" value="#Authorization#">
<cfhttpparam type="header" name="content-type" value="application/x-www-form-urlencoded">
<cfhttpparam type="header" name="date" value="#dates.signingDate#">
<cfhttpparam name="phone_number" value="#phoneNumberToCall#" type="formfield">
<cfhttpparam name="ucid" value="OTHR" type="formfield">
</cfhttp>
<cfdump var="#verifyPhoneCall#">
标题需要包含在“新行”的签名中。文档还说它们需要与http标签发送它们的顺序相同。我不认为我的顺序正确...或者甚至我应该如何在cfhttp中设置顺序调用
感谢任何帮助。是的,钥匙是真实的。我很快就会生成新的。
谢谢,
布赖恩
答案 0 :(得分:0)
查看他们在Constructing the CanonicalizedPOSTVariables Element上的文档,它提到POST主体必须与构造签名时使用的字符串匹配(强调我的):
...构造签名字符串时,必须使用正文 POST请求完全,因为它已发送到服务。
默认情况下,cfhttpparam
url会对任何formField
值进行编码。由于在构造签名时不对这些值进行编码,因此cfhttp提交的内容不匹配。因此错误。
禁用签名中所有表单字段的自动编码:
<cfhttpparam name="phone_number"
value="#phoneNumberToCall#"
type="formfield"
encoded="false">
...或者使用type =“body”代替。然后您可以完全控制帖子内容:
<cfhttpparam type="body"
value="phone_number=15554565555&ucid=OTHR">
<强>更新强>
另外,摆脱最后的新行,即“headerText”中的chr(10)。否则,您的cfhttp内容仍将与签名不匹配。即使用此:
headerText = arrayToList(headers, chr(10));
..而不是:
headerText = arrayToList(headers, chr(10)) & chr(10);