澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

iOS集成支付宝,使用及常见问题

明日做支付宝接口回调那块,不得不说,弄的自作者焦头烂额,翻了成都百货上千陈年旧帖,试了许四种缓慢解决坑的方案,在自个儿成功消除的一瞬,以为不行有不可缺少记录一下那么些坑。

前言

临时必要在地面存款和储蓄能源,并且从服务器下载能源,因为涉嫌到运营时期的安全性,有须求加多校验的逻辑,由此有了本文的有的思维。

1,支付宝申请:https://b.alipay.com/order/productDetail.htm?productId=2013080604609654&tabId=4#ps-tabinfo-hash 

iOS集成开拓宝-斯威夫特版

一经要询问整个支付流程能够阅读小说《手机App集成微信支付&支付宝-iOS&Android完整版》。
设若不想看本文的话能够直接到Github下载Demo源码。下载源码后只要求修改MyConstants.swift文件中的支付宝相关账号就能够运营。

说明

github地址

做了微信。支付宝和京东支付之后,开采,最扯蛋的开支,确定是京东开荒,要完好开辟京东费用,必要求看完京东费用开采者文档的官方网站每二个角落,相对不能够凭你的其它经验去疑忌某个流程,比如集体钥加解密(不看官方网站,保险你后悔)、发送央求的不二诀窍(form表单提交,看了官方网址你会开掘好古怪),支付同步跳转(还是post,fk),支付成功后回到居然未有开拓订单号(完全靠自身去珍重,fk)

签字验证错误的自己商酌各种(这里是依据使用官方给的demo,自个儿包裹的请绕道):

ipa包被篡改的情状

第一思量的是ipa包的安全性难点。通过iTunes,大家得以下载ipa并且解压,修改包中的文件,再压缩成ipa包。

  • 1、若是开垦者A获得应用P的ipa包,修改当中的别的公文,都会招致签字失效,ipa包无法安装。(具名存放在.app文件的_CodeSignature文件夹)
  • 2、尽管开垦者B获得应用P的ipa包,安装到温馨手提式无线话机中,再平素修改Bundle/Application 下的布局文件,此时应用P如故能够运营。
  • 3、假设开采者C获得应用P的ipa包,修改在那之中的一点配置文件,用本身的证件重签名并透过任何渠道揭橥出去,ipa包能够平常安装。

使用在通常使用进程中,app包的文书是力不从心修改的,唯有越狱的电话才会并发景况2;境况3中重签字的ipa包不可能上传AppStore。真机app安装目录是 var/mobile/Containers/Bundle/Application沙盒目录是 var/mobile/Containers/Data/Application恍如的,模拟的装置目录同样在/Bundle下,沙盒在/Data下;

澳门新浦京娱乐场网站 1

下载的财富存在沙盒目录,在未越狱的气象下,开采者并不能修改当中的文本。不过,下载财富常常使用http举办财富下载,http通过运用代理,能够非常的低价的修改下载的能源。为了确认保证下载财富的可信性,选取了一套基于奇骏SA算法的求证方案,具体的要领有:1、开采者发生一对密钥:公钥和私钥,私钥保存在安插平台,公钥放到客户端。2、当文件上传到配置平台后,配置平台对文件进摘要拿到md5str,并私钥对md5str举行签名获得signStr,然后把 文件和signStr下发给客户端。3、客户端下载文件和signStr,总结文件的摘要获得md5str,用md5str和公钥验证signStr的管用。

解释:非对称加密算法的图谋相比复杂 ,所以只对摘要进行加密;具体的流程图如下:

澳门新浦京娱乐场网站 2

普拉多SA算法的二种加密方法:

  • 公钥加密,私钥解密。(一般用于公钥持有方向私钥持有者
  • 私钥加密,公钥解密。(一般用来具名和表明,私钥加密相当于签订契约,公钥解密也正是验证)

苹果提供的Security.framework,有以下三个主意:

  • SecKeyEncrypt—encrypts a block of data using the specified key.(使用公钥对数据开始展览加密)
  • SecKeyDecrypt—decrypts a block of data using the specified key. (使用私钥对数码实行解密)
  • SecKeyRawSign—signs a block of data using the specified key.(使用私钥对数据具名)
  • SecKeyRawVerify—verifies a signature against a block of data and a specified key. (使用公钥对数字具名举行求证)

类比到OpenSSL,其提供了以下四个接口:

int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding);

因为RubiconSA算法的计算量不小,一般不会直接使用普拉多SA对数码进行加密,而是对AES的密匙进行加密,再用AES对数据加密。PAJEROSA算法原理 ,这里有一篇详细介绍EnclaveSA算法原理的作品。

iOS集成支付宝,使用及常见问题。获得后台下发的签署后,就必要保留具名,能够选拔:保存在文书中、保存到NSUserDefault、保存到数据库等。除此而外,是或不是能够保存在文件属性?写了一段代码进行测试:

 NSMutableDictionary *changedAttrDict = [[NSMutableDictionary alloc] init]; [changedAttrDict setObject:@"loying" forKey:NSFileOwnerAccountName]; [changedAttrDict setObject:@"NSFileGroupOwnerAccountName" forKey:NSFileGroupOwnerAccountName]; [changedAttrDict setObject:[NSDate dateWithTimeIntervalSinceNow:3600] forKey:NSFileCreationDate]; NSError *error; BOOL ret = [[NSFileManager defaultManager] setAttributes:changedAttrDict ofItemAtPath:encodedDataPath error:&error];

透过测试,NSFileCreationDate这性子子是能够修改的;NSFileGroupOwnerAccountNameNSFileOwnerAccountName不能够修改(真机为@"mobile");模拟器不得以修改多个个性,最大的大概性是因为模拟器运营发生的公文,权限远远不够修改文件属性;createDirectoryAtPath:withIntermediateDirectories:attributes:本条点子一致有其一界定。写入文件属性还大概有其余的限制,当文件在区别硬盘格式(HFS and FAT32)拷贝的时候,文件附带的天性或者会消退。

NSFileProtectionKey 是后台形式下的文书读写

为了支付方便人民群众,能够挑选保存到NSUserDefault的诀窍。新建NSMutableDictionary,用文件作为key,用FileConfig作为value。FileConfig是验证相关的习性封装,便于后续开拓。

1、NSUserDefault全部的性质最后会写入Libary/Preference/下的plist文件中,所以NSUserDefault中不能够储存敏感消息。

2、假设赶过错误:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object这是因为NSUserDefault只好存基本项目,倘若dict里面存有自定义类型,要求先转成NSData再囤积;(plist里面未有组织音讯,只有key-value)

2,开采文书档案:https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1 

申请PID

到支付宝商家庭服务务网页申请快速支付。

工夫描点

第一要去看官方网站的:http://payapi.jd.com/。 项目应用的是pc网页支付

一. 联合下单的接口:iOS集成支付宝,使用及常见问题。https://wepay.jd.com/jdpay/saveOrder

参数表明:http://payapi.jd.com/docList.html?methodName=2

必然要致密的看那么些参数的求证

独特参数表明如下:

  1. 在上述的乞求参数中,店家号是在登记开通京东支付成效的时候,京东开采经纪人管理体系为用户分配的。
  2. 用户账号是商人系统的用户账号。
  3. 贸易流水号是用来标记每一回支付央求的号子,须要经纪中国人民保险公司险在每一次支付央求的时候交易流水号唯一,多次伸手无法选取一样交易流水号,不然京东支付劳动在管理后边的支出乞求时,会把此交易作为重复费用管理。
  4. 签名规则详见:“接口安全规范-签字算法”;
  5. 为保险音信安全,表单中的种种字段除了merchant(商行号)、版本号(version)、签字(sign)以外,别的字段全体用到3DES开始展览加密。

二. 生成签字

签字进度分成两步,首先是将原有参数遵照规则拼接成二个字符串S1,然后再将S1基于签订契约算法生成签字字符串sign。
参数原始字符串的拼凑规则:

  1. 对此POST表单提交的参数:全部参数依照参数名的ASCII码顺序从小到大排序(字典序),使用U凯雷德L键值对的章程拼接成字符串S1,(如:k1=value1&k2=value2&k3=value3…)
  2. 对于XML报文交互的参数:将XML报文的各行去掉空格后一向拼接成一行字符串作为S1。尽管报文唯有一行则向来作为S1,无需再拓展拼接。

扭转签字的长河如下:

  1. 对拼接的参数字符串S1经过SHA256算法总结摘要,获得字符串S2;
  2. 对字符串S2使用私钥证书实行加密,并张开base64转码,获得具名字符串sign; 接收方收到报文后先实行base64解码,再使用公钥证书解密,然后验证具名的合法性。

注意事项:

  1. 空参数不加入签署;
  2. 参数列表中的sign字段不参与签署;
  3. 为了简化管理,<xml>标签也加入签署;
  4. 参数区分轻重缓急写;
  5. 澳门新浦京娱乐场网站,兰德逍客SA加密的规则为:由交易发起方进行私钥加密,接收方进行公钥解密;(可以使用TiggoSA公私钥校验工具来校验商行HighlanderSA公私钥是或不是合营)
  6. 系统会对经纪人公钥证书的可行举行校验。

签字代码:

def get_sign_str(params, is_compatible=False):
    """
    生成签名的字符串
    Args:
        params: 签名的字典数据
        is_compatible: 是否是兼容模式(对字典中value值为空的也签名)

    Returns:
        返回签名
    """

    raw = [(k, params[k]) for k in sorted(params.keys())]
    if is_compatible:
        order_str = "&".join("=".join(kv) for kv in raw)
    else:
        order_str = "&".join("=".join(kv) for kv in raw if kv[1])

    return order_str



def sign(self, prestr):
    """
    生成签名
    Args:
        prestr(str): 生成签名的原字符串

    Returns:
        返回生成好的签名
    """
    key = MRSA.load_key(self.MERCHANT_RSA_PRI_KEY)
    signature = key.private_encrypt(self.sha256(prestr), MRSA.pkcs1_padding)
    sign = base64.b64encode(signature)
    return sign

三. DES3对每一个参数进行加密(merchant(商户号)、版本号(version)、署名(sign)除了那么些之外)

为防范明文数据在post表单提交的时候暴露,所以京东做了DES3对字段举行加密(不用表单提交不就行了,还搞这么复杂,真该学习支付宝和微信)

京东DES加密表明如下:

   除特定说明外,商户和京东支付接口调用报文采用3DES加密,再通过base64转换为字符串。
   3DES加密算法标为DESede,工作模式为电子密码本模式ECB,不填充(DESede/ECB/NoPadding)。
注:服务端NoPadding 为不填充,所以加密的原文字节必须是8的整数倍(如果调用我们提供的加密接口API则不必处理原文字节,加密接口内部已处理)。如果自己实现加密,原文字节不够8的整数倍,则按如下规则转为8的整数倍。
    1.  把原文字符串转成字节数组。
    2.  根据字节数组长度判断是否需要补位。
        补位逻辑为:
        int x = (i  4) % 8;
        int y = (x == 0) ? 0 : (8 - x);
        i为字节数组的长度,y为需要补位的长度。
        补位值为0。
    3.  将有效数据长度byte[]添加到原始byte数组的头部。
        i为字节数组的长度。
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);

    4.  原文字节数组前面加上第三步的4个字节,再加上需补位的值。
        例如:字符串”1”,转换成字节数组是[49],计算补位y=3, 计算有效数据长度为[0, 0, 0, 1],最后字节数组为[0, 0, 0, 1, 49, 0, 0, 0]。
Form表单接口的加密方式:
如果商户通过表单方式提交支付请求至收银台,为保证信息安全,表单中的各个字段除了merchant(商户号)、verion(版本号)、sign(签名)以外,其余字段全部采用3DES进行加密。

XML请求接口的加密方式:
通过XML接口方式和京东支付服务器交互的请求,应该对报文进行加密,加密方式为对整个报文整体进行3DES加密,再进行base64转码使其变为可读字符串,加密后的密文置于<encrypt></encrypt>标签中,同时再将报文中的<merchant>(商户号)、<version>(版本号)这两个字段单独置于<jdpay>标签下。

接收到京东支付加密报文后的处理方式:
接收到京东支付返回的加密报文后,先判断<jdpay>标签下的<result>标签的返回码,检查接口调用是否正常返回。然后再读取<encrypt>标签的密文内容进行base64解码,再进行3DES解密,解密后的报文即是原始报文。

演示代码:

def des_pad(data):
    e = len(data)
    x = (e   4) % 8
    y = 0 if x == 0 else 8 - x
    sizeByte = struct.pack('>I', e)
    resultByte = range(len(sizeByte)   e   y)
    resultByte[0:4] = sizeByte
    resultByte[4:4   e] = data
    for i in range(0, y):
        resultByte[e   4   i] = "x00"
    resultstr = ''.join(resultByte)
    return resultstr


def encode_des(to_encode_str, des_key):
    """
    DES3加密数据
    Args:
        to_encode_str(str): 要被加密的原字符串,这里的字符串需要被des_pad一下
        des_key(str): 加密的key
    Returns:

    """

    key = base64.b64decode(des_key)
    des3 = DES3.new(key, DES3.MODE_ECB)
    return des3.encrypt(ToolsClass.des_pad(to_encode_str)).encode('hex_codec')

那样的话,具名和加密都已成功,以后就拼到页面里的form里

 <form method="post" action="https://wepay.jd.com/jdpay/saveOrder" id="batchForm">
        <input name="merchant" type="hidden" id="merchant" value="22294531" /><br/>
        <input name="notifyUrl" type="hidden" id="notifyUrl" value="da652ac3b881c4ddc2ac26793b20c37fba91a994f108bf8a0a42b5ead05111997bfe2a97eaf4aa49562de1b6d1d32cd7" /><br/>
         <input name="userId" type="hidden" id="userId" value="f23f2b73027cb0f8deb349af3086fdc50f6892f17c9f45b81b6d273d0cdb1cae8151f083427fc8f0" /><br/>
            <input name="sign" type="hidden" id="sign" value="SJ6qfS 9CmXkt6ghJcf9nIdHJDReTFNkRyjFh5XZAsTAtfHT4SdmKeD88t 2dMnaszJ7vVjBnSu64aJyt6SODW2FHJk0WXEvZNixmo2h8F7vHO5lTE2jEG/9uN7sqg2c7kH2Fnu5cFLCeaMfb8uZqZ8CKi g7Aw4b6rywvoH/8M="
        /><br/>
        <input name="currency" type="hidden" id="currency" value="ac7132c57f10d3ce" /><br/>
         <input name="orderType" type="hidden" id="orderType" value="e00c693e6c5b8a60" /><br/>
         <input name="tradeNum" type="hidden" id="tradeNum" value="05439876d54534c7604c42eca17c14cdf8eece390982627a0799194a74809ee6c9d07d3cff8a7c60"
        /><br/>
         <input name="amount" type="hidden" id="amount" value="e5a6c3761ab9ddaf" /><br/>
        <input name="version" type="hidden" id="version" value="V2.0" /><br/>
        <input name="tradeTime" type="hidden" id="tradeTime" value="d9668085c69c2ecb33367c0710f42c4bc7432967ba39f140"
        /><br/> <input name="tradeName" type="hidden" id="tradeName" value="3e111657e2839e3a3ba10d54bb446817e5000daf14a2e3badbf9a93316ed6003" /><br/>
        <input name="callbackUrl" type="hidden" id="callbackUrl" value="51c916293675ac44c2ac26793b20c37fba91a994f108bf8a0a42b5ead05111997bfe2a97eaf4aa49229a23b8c688e767"
        /><br/><input type="submit" />
    </form>

怎么协会就自个儿去贯彻好了

四. 异步回调

提交以往乞请之后,就能够跳转到京东的支出页面,可登陆账户支付,也可用京东app可能微信扫描支付。

当用户扫码支付之后,京东会主动跳转到你钦命的三个网站(在付出支付诉求的时候有其一字段),并且会异步post二个伸手到钦命的四个地方(在提交支付须求的时候有其一字段),同步跳转是在用户扫码支付之后,借使京东开销页面还在的话会跳转。而异步是无论怎么着都会发支付结果通报的。对于生手来讲,一定要理解这么些行业不成文规则(微信,支付宝or别的都是)。而且必然要以那一个异步文告的结果为准。

京东回来的是xml格式的字符串

归来格式如下(没有换行的,作者那边演示换了行的):

<?xml version="1.0" encoding="UTF-8" ?>
<jdpay>
<version>V2.0</version>
<merchant>22294531</merchant>
<result> <code>000000</code> <desc>success</desc> </result>
<encrypt>MWYxMjBjMzViZjgwOWM5ZDhjNjc0YmY1ZWJlY2QyODU0YTc5NmQ3ZWQxMWU1NzE3MWQ0OTUwOGI5NzllYmE4ZjM1YzRiZjlmYWE1M2ZiYjVmYzBmYTgyMDYyM2Q0YjM0NGM1ODFkZDhlYTA2Mjk0ZDE5ZDBlZDk5NTc3MmE4Nzk4OTFlYjIwZDgzMTc4MDU3NGVkZTFjNDY0MDMzNzNjZjc2OWZiMDQ0YjVhZGNhYmRhMGZmYTkyNzRhZDNhM2IxOGY5ZjZhYjBmYjhmZmI3Yzg0OTA3YzM0OGJmZTYwZTIzNzM3YjVmYzMzNmNkYTE0MjM2OWIwZDM5MjI2YWM5YmY3ZmZjZDBkNWJmM2ZkYWY4YTU3OWU4MDE3ZjQ5YmQ0ZWIyMDA0NTFmODZkNmViMDBiMDE2YTU3NTNjMzJjNDIzNWI5ZDkyYzQ3OTU4OTc2ZGIyZmNiMGUxNGRjNTM2OGZjYjQ0NmE0YWY1ZWVjZDYzNWI5ZDkyYzQ3OTU4OTc2NmIwM2QyZTU1ODJlNDNjM2M1NjA2YmQ5ZDc3MTRkMmNjN2ZiMDM3Yzg5ZDk1ODFkMWJhZmVjYjUwMzJlNTdkMTFmN2QxMDAxNjgyMzJjNTZhMmQzNTcyZGE4OTUzYWFjNTU5MDY4YWYyODE5ZDcyNmY5NmE1YTBmYWFiZTRiZTQ2OGZhMmM4M2JjMGM5NmNiMDE3ZWQ4MDkxY2FjZThiNzg4MjY5OWY1ZTJlYzBjOTIxODBhOGExNjExNGY4NWQwM2NkZjI2MTFmM2VmODcxYWM3MjUxZjMxMzZlYjFmNzI1NWE0OWM4MjMxZGY1MzBmY2Y1Mjg2NGUzMWRlMjc0M2I5ZDM5NjQzN2ZmZWQ1Y2M5NDY4ZDcwNWM1YzVhZmRlYzYwZWU3MDVhNjE0N2I1MGVlM2UyMGE2MzExNTE4YTUxOGRjMzBmMmUxZjE2NzYzNGRiNDJlODFmMDczOGYzZjMxN2NkMjkzNmU4ODc3NzJjMjkzM2ZlODlmMjUyNDVmNDI2MDA0M2VkYmUwOTlkNGEyNjU3YTM5YTE4ODU2OTBmNGQyNDcwZDE0ZWRjMmQxYjgxMzhhNjA5M2ZlNDkxYTQyMzE5YzBlNTA0MTdkYTg2ZGQ2NDQwODBmMjM4ZGI2YzIzMjNhOTE0M2VmMjZiZjczN2M5NWQwODYxMWY2OGE5MDQ0ZDZmNzE0NmIxZjQwZDdmZDMxOTQ2ZDM3YjIwNDJiODUzZGM0NTk0MzM5YzJkN2M2NDdiNGM4MzQ4MTRjZTIxZTlmYTYzNDYxNGMxMjlhZTE3NjE0ZDIzM2Q2MTQ4YzJiNWE3ZWVjMDU5MjFmNzJkNGNjNTU1NWZkNzVhN2U5Y2I1MDU1NjhlMWRlNjVhNzkyOGUxMThlODQyMGJkNzE2NjdmMDc3YmEyYTFkNmQyOTFiOGNjZTU2ZGMyYmE3ODY5ZGZiNmMyMWViYjc2ODc0Y2I3YTc4NGQ5NWY2NjY2Y2E5NjI0N2I1MGE4MTliMDBkNGIzNmViZTJlY2JmYTcwODUzYTM5ZTcwMDVmYWEzNWY2MDFhMWM2MGQ1MzEyYmQxNDU3Zjg4ZWVhNzY2YjZhOGE4ZGMxMGY3NjYwOWEzNWY2MDFhMWM2MGQ1MzFhNzA4NTNhMzllNzAwNWZhYTYxMmJmNjJiMmFlMGY5ODMxMzQ0MzQ0NjMxZDc3MTUyY2FiMjZlMjcyYmJjYmQzODVmNDY4OTA5YTdjMjlmNTI5NWFlZjE3NTI4ZmE4MzVhNzA4NTNhMzllNzAwNWZhNDk5OTQ2ZGU0OGU0NGQ2ZTE4YmRiYTBjZjNhM2ZkNjY5ODJjNGVhZjQzMjIyYWFhMWM0ZmU1ODRiNTg5OWEwYzAwNjI2NTllMDZkYzhiYTVmMjI3ZjUyYmQ3MjcyODllZmEwYzhiNDIwODc4ZjUzODY1MzAzZDkyNDM5OTRkNDczMTBjZDBhMTc4ZjAwOTIyZmM2ODk5YjkyYTJiODcwNjU4MzkzMzJkZWYzNDY1MzJlYTNiYTFhNjM0MWIwNjM4NjBjNjlmMzg1NWZjZWM5YWExMDdjZWY1MjkwZTZjMzgzOGYxNTRiNzFlN2E1YTczYWFkNzJlOTRiOWI3MmI2YWYyMTJjMjQ5Y2UzMmUxMGI4YWE0N2YzYzFmNjNiOGY4NjJlZmU1ZDM5NjcwODA3MGNjY2JjYWFkYjM3NzBmMGQzYjIyMGFmZTE3YWNjZWU1N2RmZTQxMzAxYjA2MDdlMg==</encrypt>
</jdpay>

先要用DES3对encrypt节点里的串进行解密

def un_des_pad(data):
    resultByte = data[0:4]
    e = struct.unpack('>I', resultByte)[0]
    x = (e   4) % 8
    y = 0 if x == 0 else 8 - x
    return data[4:] if y == 0 else data[4:-y]

def decode_des(to_decode_str, des_key):
    """
    解密数据
    Args:
        to_decode_str(str): 要解密的原字符串
        des_key(str): 解密的key
    Returns:

    """
    key = base64.b64decode(des_key)
    des3 = DES3.new(key, DES3.MODE_ECB)
    param = to_decode_str.decode("hex_codec") if to_decode_str is bytes else base64.b64decode(to_decode_str).decode(
        "hex_codec")
    param = des3.decrypt(param)
    return ToolsClass.un_des_pad(param)


sign_begin = xml_data.find('<encrypt>')
sign_end = xml_data.find('</encrypt>')
encrypt_str = xml_data[sign_begin   9:sign_end]
xml_str = JdPay.decode_des(encrypt_str, deskey)

解密后的掌握如下:

<?xml version="1.0" encoding="UTF-8" >
<jdpay>
  <version>V2.0</version>
  <merchant>110290193003</merchant>
<result>
  <code>000000</code>
  <desc>success</desc>
</result>
<device>6220</device>
<sign>SJ6qfS 9CmXkt6ghJcf9nIdHJDReTFNkRyjFh5XZAsTAtfHT4SdmKeD88t 2dMnaszJ7vVjBnSu64aJyt6SODW2FHJk0WXEvZNixmo2h8F7vHO5lTE2jEG/9uN7sqg2c7kH2Fnu5cFLCeaMfb8uZqZ8CKi g7Aw4b6rywvoH/8M=</sign>
<tradeNum>201704250935156041484635</tradeNum>
<tradeType>0</tradeType>
<amount>3140</amount>
<status>2</status>
<payList>
  <pay>
    <payType>3</payType>
    <amount>1500</amount>
    <currency>CNY</currency>
    <tradeTime>20170425093516</tradeTime>
 </pay>
 <pay>
   <payType>1</payType>
   <amount>1640</amount>
   <currency>CNY</currency>
   <tradeTime>20170425093516</tradeTime>
   <detail>
     <cardHolderMobile>150****1596</cardHolderMobile>
   </detail>
  </pay>
</payList>
</jdpay>

解密之后正是认证签字是或不是科学,从下边包车型客车串中得到签订契约和去除签字之后的字符串

def verify_mysign(cls, sign, xml_str, jd_public_key):
    """
    验证签名
    Args:
        sign: 签名
        xml_str: 去除签名后的xml字符串
        jd_public_key: 用于验证的key

    Returns:

    """
    xml_sha_str = SHA256.new(xml_str).hexdigest()
    key = MRSA.load_pub_key(jd_public_key)
    signature = key.public_decrypt(base64.standard_b64decode(sign),
                                   MRSA.pkcs1_padding)
    return signature == xml_sha_str

表明通过之后再重临去除sign的xml字符串,并提收取里边的内容(详细情况参数所表示的意思请看官方文书档案)

五. 同步跳转

四头跳转就没啥好说了,只是给个跳转地址,然而此间一定要留心,那些的是三个post伏乞(好像京东啥都喜欢post),而非微信依旧支付宝照旧other什么的get伏乞。所以并非设置错了

好了,到此地一个完全的在线支付就做到了。这里还要表明的是,涉及到加密和平消除密,就决然会有key,有DES3行使的相辅相成加密key,还应该有签名使用的非对称公钥和私钥。所以必然要安排好。
此处小编的源代码里用的都以京东提供的测试商户号,还应该有一大推京东设置好的key,具体要去下载京东的【京东支付PC&H5接口文书档案】,在文书档案的最底部有帐号消息。

demo里边还大概有申请退款,申请撤单的接口,其实写好三个接口的成功流程,别的流程都以直接套用就足以了。

1:检查一下你利用的表达签字的艺术是或不是正确?

总结

别的花招都没有办法儿完全防止恶意的口诛笔伐,只可以升高门槛。

3,载入aplipay库,关联类库

SDK

首先从支付宝开放平台下载SDK. 解压后的目录下富含「服务端demo」和「客户端demo」。「客户端demo」包蕴了集成支付宝所急需的富有文件。

bool signVerified = AlipaySignature.RSACheckV1(dic, alipay_public_key, config.charset);

附录

iOS使用Security.framework实行MuranoSA 加密解密签字和表明签字

4,用申请到的seller(商行支付宝号),partner(厂商PID:2088***********),private key(私钥途睿欧SA转码后的一串字符)连接支付宝服务器,生成订单,加密,具名,设置schema,设置服务器端的回调地址

RSA加密

漫天支付流程小编在小说《手提式有线电话机App集成微信支付&支付宝-iOS&Android完整版》中有详细描述。
为了确认保证卫安全全,幸免支付结果被截获,在变化订单和拍卖支付结果的时候就要求做安全校验。生成订单时对数据具名,收到支付结果时对数码举办签名验证,以验证数据是或不是被篡改过。支付宝方今采纳福特ExplorerSA加密方法做签字验证。

KugaSA加密算法除开可加解密外,还可用来作具有名学校验。
简易的说,中华VSA会生成二个私钥和叁个公钥,私钥你应当单独保管,公钥你能够分发出去。
做签字验证时,你可以用私钥对要求传输的多寡做具名加密,生成贰个签订契约值,之后散发数据,接收方通过公钥对具名值做校验,假设同样则以为数额无篡改。
调换公钥和私钥

用openssl生成商家的公钥和私钥,私钥用于提交支付申请时加密,而公钥要在商家庭服务务页面上交给,换取到支付宝的公钥。
对此iOS来讲,私钥要转为PKCS8格式,即下述代码的第三行!

openssl genrsa -out rsa_private_key.pem 1024 
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem 
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt 

 

5,客户端支出成功,由开采宝客户端回调应用客户端,支付宝服务器回调系统后台服务器

链接库

第一把 AlipaySDK.framework 和 阿里paySDK.bundle 拖到你的项目里面。然后把demo目录上面的openssl和Util四个目录拖到你的工程上边。然后在 Build Settings => Header Search Paths => 增添 "$(S奥迪Q5CROOT)/openssl" 和 "$(SHighlanderCROOT)/Util"
再不会有邻近报错:"openssl/asn1.h file not found"。

在Build Phases选项卡的Link Binary With Libraries中,增添以下信赖:

澳门新浦京娱乐场网站 3

alt text

里面,需求专注的是:
纵然是Xcode 7.0随后的版本,要求增添libc .tbd、libz.tbd;
一旦是Xcode 7.0事先的本子,必要增多libc .dylib、libz.dylib

新建叁个Bridging-Header.h文件,并把该公文的路径加多到 Build Settings => Objective-C Bridging Header。然后在该文件中增多上面两行:

#import <AlipaySDK/AlipaySDK.h>   
#import "RSADataSigner.h" 

要是您的服务器不协理Https,请在info.plist文件里面增添如下代码:

 <key>NSAppTransportSecurity</key> 
 <dict> 
   <key>NSAllowsArbitraryLoads</key> 
   <true/> 
 </dict> 

出于支付包支付成功后必要再次来到App,那么您就须求设置你App独有的Schema:采纳你的品类,选取Info,在U陆风X8L Types中增添贰个schema,并设置Url Schemas.

Coding

到这一步,整个配置进度就曾经成功了。上边包车型地铁行事正是Coding部分了。

let aliOrder = AlipayOrder(partner: AlipayPartner, seller: AlipaySeller, tradeNO: order.id, productName: order.title, productDescription: order.content, amount: order.price, notifyURL: AlipayNotifyURL, service: "mobile.securitypay.pay", paymentType: "1", inputCharset: "utf-8", itBPay: "30m", showUrl: "m.alipay.com", rsaDate: nil, appID: nil)


    let orderSpec = aliOrder.description //orderA.description

    let signer = RSADataSigner(privateKey: AlipayPrivateKey)
    let signedString = signer.signString(orderSpec)

    let orderString = "(orderSpec)&sign="(signedString)"&sign_type="RSA""

    print(orderString)

    AlipaySDK.defaultService().payOrder(orderString, fromScheme: AppScheme, callback: {[weak self] resultDic in
        if let strongSelf = self {
            print("Alipay result = (resultDic as Dictionary)")
            let resultDic = resultDic as Dictionary
            if let resultStatus = resultDic["resultStatus"] as? String {
                if resultStatus == "9000" {
                    strongSelf.delegate?.paymentSuccess(paymentType: .Alipay)
                    let msg = "支付成功!"
                    let alert = UIAlertView(title: nil, message: msg, delegate: nil, cancelButtonTitle: "好的")
                    alert.show()
                    //strongSelf.navigationController?.popViewControllerAnimated(true)
                } else {
                    strongSelf.delegate?.paymentFail(paymentType: .Alipay)
                    let alert = UIAlertView(title: nil, message: "支付失败,请您重新支付!", delegate: nil, cancelButtonTitle: "好的")
                    alert.show()
                }
            }
        }
        })

阿里payOrder的description属性如下:

var description:String {
    var desc = ""
    desc  = "partner="(partner)""
    desc  = "&seller_id="(seller)""
    desc  = "&out_trade_no="(tradeNO)""
    desc  = "&subject="(productName)""
    desc  = "&body="(productDescription)""
    desc  = "&total_fee=""   amount.format("0.2")   """
    desc  = "¬ify_url="(notifyURL)""
    desc  = "&service="(service)""
    desc  = "&payment_type="(paymentType)""
    desc  = "&_input_charset="(inputCharset)""
    desc  = "&it_b_pay="(itBPay)""
    desc  = "&show_url="(showUrl)""

    if let rsaDate = rsaDate {
        desc  = "&sign_date=(rsaDate)"
    }

    if let appID = appID {
        desc  = "&app_id=(appID)"
    }

    return desc
}

2:检查一下你传入的参数是还是不是科学?

6,消除办法

布告服务器支付成功

一旦开荒成功后,支付宝服务器会向您的服务器 notify ULacrosseL 发起支付成功的伸手。那样就能够在服务端完毕部分有关的事情逻辑,举个例子标志订单为已支付,发短信给用户等。notify USportageL的现实性贯彻请查看文章《iOS&Android集成开采宝-server篇(PHP)》

翻看完整代码请移步Github

参数1:dic,把回调的参数保存到key,value集结中

1、报错:rsa_private read error : private key is NULL

Dictionary<string, string> dic = new Dictionary<string, string>();
var form = HttpContext.Current.Request.Form;
string str = "异步通知:rn";
foreach (var key in form)
{
   dic[key.ToString()] = HttpContext.Current.Request.Form[key.ToString()];
   var value = HttpContext.Current.Request.Form[key.ToString()];
   //记录日志使用
   str  = $"{key.ToString()}:{value}rn";
}

原因:私钥没有转成PKCS8

参数2:alipay_public_key

1)、在LacrosseSKingstonSigner.m文件中检索代码[result appendString:@"-----BEGIN PRIVATE KEY-----n"];将其改成[result appendString:@"-----BEGIN RSA PRIVATE KEY-----n"];

本条参数是 支付宝公钥!!   大多同伙都写成了利用公钥,瞎几把写。

2)、在宝马X3SAntecSigner.m文件中查找代码[result appendString:@"n-----END PRIVATE KEY-----"];将其改成[result appendString:@"n-----END RSA PRIVATE KEY-----"];

参数3:编码格式,UTF-8,那么些貌似没人会错。

7,加密解密的长河:https://cshall.alipay.com/support/help_detail.htm?help_id=397433&keyword=%C8%E7%BA%CE%C9%FA ,是客户端生成的,

 

生成私钥命令:genrsa -out rsa_private_key.pem 1024

转移格式:OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

扭转公钥:OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

3:检查一下你的境况,沙盒蒙受依然线上遭受,沙盒情形会出错,具体怎么小编不了然,百度来的。要在支付宝中给你的回调域名授权,不授权人家懒得回调给您。

8,在大切诺基SA的具名时,要求私钥和公钥一同参加签署。私钥与公钥皆是客户通过OPENSSL来变化得出的。客户把生成出的公钥与支付宝本事人士配置好的支付宝公钥做交流。由此,在签署时,客户要用到的是客户的私钥及支付宝的公钥。

 

9,支付宝sdk集成,报系统繁忙请稍后再试(ALI64),公私钥不匹配,必须本机生成公钥私钥么

4:检查一下你的加密解密类型,作者从官方网址下载下来的demo里面包车型地铁解密类型默许是瑞虎SA,不过官方文书档案已经明朗说明现行都要用奇骏SA2了,所以记得检查demo的源码

10,上传公钥:https://cshall.alipay.com/enterprise/help_detail.htm?help_id=473890 

public static bool RSACheckV1(IDictionary<string, string> parameters, string publicKeyPem, string charset)
{
   string sign = parameters["sign"];
   string sign_type = parameters["sign_type"];
   parameters.Remove("sign");
   parameters.Remove("sign_type");
   string signContent = GetSignContent(parameters);
   return RSACheckContent(signContent, sign, publicKeyPem, charset, sign_type);
}

11,seller,partner:签订契约后,支付宝会为各个厂商分配三个唯一的parnter和seller。

sign_type,那几个正是解码类型,demo写的接近“大切诺基SA”,小编这里改成动态获取了,大家在最初配置的地点也会布置加密类型,从哪获取都能够,别弄错了就行。

12,公钥必须给支付宝,不然他们解密不了啊,然后支付宝再次来到数据再用支付宝的私钥加密,然后用支付宝给的公钥解密,o my god.

 

公钥加密方法,对称,加密解密同样的,非对称,非对称正是加密和平解决密的区别规则,HavalSA代表多少个贱人,

5:这里不反省了,回忆一下你的支付宝公钥,是直接存在文本中的,依旧写在代码里的(差别:公钥.txt,string 公钥 = “巴拉巴拉巴拉一大堆”),一个是文件,二个是一贯代码(笔者就是代码,所以自个儿直接到最后才消除)(上面包车型客车化解方案只针对代码保存支付宝公钥的骚年)

13,先与支付宝签约,得到商户ID(partner)和账号ID(seller)

string alipay_public_key = "-----BEGIN PUBLIC KEY-----rn"   config.alipay_public_key   "-----END PUBLIC KEY-----rnrn";
bool signVerified = AlipaySignature.RSACheckV1(dic, alipay_public_key, config.charset);

(那么些着重是信用合作社的承受),下载相应的公钥私钥文件(加密签署用),私钥文件不是下载的,2了吧,

一旦是一向写在代码中的,要给支付宝公钥的头跟尾加上标志,具体标志看本身贴出来的代码,如若是文本,请自行忽略

14,由服务器来生成订单,然后回来订单字符串:

还没得了,官方给的demo也是默认找的文件,可是我用的代码存的,哪有文件,所以找不到文件是会报错的,报错直接再次来到false了,在改变一下源码(本身到AlipaySignature那么些类里面去找)

NSString * dataString = [responseObject valueForKeyNullReplace:@"data"];

public static bool RSACheckContent(string signContent, string sign, string publicKeyPem, string charset, string signType)
{

    try
    {
        if (string.IsNullOrEmpty(charset))
        {
            charset = DEFAULT_CHARSET;
        }

        if ("RSA2".Equals(signType))
        {
            //这里就是要改的地方
            //从参数获取
            string sPublicKeyPEM = publicKeyPem;
            //从文件获取
            //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.PersistKeyInCsp = false;
            RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);

            bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), "SHA256", Convert.FromBase64String(sign));
            return bVerifyResultOriginal;

        }
        else
        {
            //这里就是要改的地方
            //从参数获取
            string sPublicKeyPEM = publicKeyPem;
            //从文件获取
            //string sPublicKeyPEM = File.ReadAllText(publicKeyPem);
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.PersistKeyInCsp = false;
            RSACryptoServiceProviderExtension.LoadPublicKeyPEM(rsa, sPublicKeyPEM);

            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
            bool bVerifyResultOriginal = rsa.VerifyData(Encoding.GetEncoding(charset).GetBytes(signContent), sha1, Convert.FromBase64String(sign));
            return bVerifyResultOriginal;
        }

    }
    catch (Exception e)
    {
        NLogGetter.NLog.ErrorLog(e);
        return false;
    }

}

int ret = [alixpay pay:dataString applicationScheme:appScheme];

好了,差不离就总结了那般多,基本上能够让你签字验证成功了。

1,支付宝公司账户签订契约飞速支付猎取商行id,账户id

2,用openssl生成公钥,私钥,上传公钥,下载其余多个公钥

3,生成订单音讯,设置回调U奥迪Q5L,schema,用瑞鹰SA加密,发起支付

4,支付结果回调客户端,客户端管理,

本文由澳门新浦京娱乐场网站发布于www.146.net,转载请注明出处:iOS集成支付宝,使用及常见问题