iOS集成Adyen HPP支付一直提示merchant signature not valid错误如何解决
问题描述
我正尝试通过HPP方式在iOS中集成Adyen支付,持续出现Merchant signature was not valid报错,我怀疑是编码环节存在问题。
iOS端原代码片段
var urlComponents = URLComponents() urlComponents.queryItems = [] let contentKeys1: [String] = Array(content.keys) for contentKey in contentKeys1 { if let contentValue = content[contentKey] { urlComponents.queryItems?.append(URLQueryItem(name: contentKey, value: contentValue)) } } self.httpBody = urlComponents.query?.data(using: .utf8)
Android端同款逻辑运行正常,我将Android生成的请求字符串拿到iOS侧测试,支付页面可以正常打开无报错。
Android端参考代码片段
val query = StringBuilder() if (providerDataset != null) { for (providerData: ProviderData in providerDataset) { val key = providerData.key var value: String? = "" try { if (providerData.value != null) value = URLEncoder.encode(providerData.value, StandardCharsets.UTF_8.toString()) } catch (e: UnsupportedEncodingException) { e.printStackTrace() } val str = "$key=$value" query.append(str).append("&") } } return query.deleteCharAt(query.length - 1).toString()
请问iOS侧有没有可以实现和上述Android代码相同效果的编码方法?

解决方案
问题根因是iOS系统的URLComponents默认的query编码规则不符合application/x-www-form-urlencoded标准要求,和Android端使用的URLEncoder.encode编码结果不一致,导致Adyen签名校验失败。具体差异点在于URLComponents不会把空格编码为+,也不会对~、/等特殊字符做编码,而Adyen的签名生成逻辑是严格按照表单编码规则处理的。
可以通过自定义编码规则对齐Android端实现,替换原有生成请求体的逻辑即可:
// 先给String加自定义编码扩展 extension String { func adyenFormEncoded() -> String { let allowedCharacters = CharacterSet(charactersIn: "*-._0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") return self.addingPercentEncoding(withAllowedCharacters: allowedCharacters)? .replacingOccurrences(of: " ", with: "+") ?? "" } } // 替换原有的请求体生成逻辑 var queryItems: [String] = [] let contentKeys = Array(content.keys) for contentKey in contentKeys { if let contentValue = content[contentKey] { let encodedKey = contentKey.adyenFormEncoded() let encodedValue = contentValue.adyenFormEncoded() queryItems.append("\(encodedKey)=\(encodedValue)") } } let queryString = queryItems.joined(separator: "&") self.httpBody = queryString.data(using: .utf8)
上述实现和Android端URLEncoder.encode逻辑完全一致,生成的请求参数和Android端无差异,即可解决签名校验失败的问题。
内容的提问来源于stack exchange,提问作者Prasad Devadiga
相关产品推荐
相关产品推荐

