您的位置:首页 > 移动开发 > IOS开发

ios 支付宝:移动支付1

2016-05-03 14:50 549 查看


接移动支付只需要上面的东西就OK

//
// Order.h
// AlixPayDemo
//
// Created by 方彬 on 11/2/13.
//
//

#import <Foundation/Foundation.h>

@interface Order :
NSObject
//签约的支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。
@property(nonatomic,copy)NSString * partner;//2
partner

//卖家支付宝账号(邮箱或手机号码格式)或其对应的支付宝唯一用户号(以2088开头的纯16位数字)
@property(nonatomic,copy)NSString * seller;//10
seller_id

//商户网站唯一订单号:支付宝合作商户网站唯一订单号
@property(nonatomic,copy)NSString * tradeNO;//7
out_trade_no

//商品名称:商品的标题/交易标题/订单标题/订单关键字等。该参数最长为128个汉字****
@property(nonatomic,copy)NSString * productName;//8
subject

//String(512) 商品详情:对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body*******
@property(nonatomic,copy)NSString * productDescription;//12
body

//总金额:该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位
@property(nonatomic,copy)NSString * amount;//11
total_fee

//服务器异步通知页面路径:支付宝服务器主动通知商户网站里指定的页面http路径
@property(nonatomic,copy)NSString * notifyURL;//6
notify_url

//接口名称,固定值。
@property(nonatomic,copy)NSString * service;//1
service

//支付类型。默认值为:1(商品购买)
@property(nonatomic,copy)NSString * paymentType;//9
payment_type

//商户网站使用的编码格式,固定为utf-8
@property(nonatomic,copy)NSString * inputCharset;//3
_input_charset

//未付款交易的超时时间
@property(nonatomic,copy)NSString * itBPay;//30m,可空
//客户端号
@property(nonatomic,copy)NSString * appID;//可选

@property(nonatomic,copy)NSString * showUrl;//不需要的参数
@property(nonatomic,copy)NSString * rsaDate;//不需要的参数
@property(nonatomic,readonly)NSMutableDictionary * extraParams;//不需要的参数

//4 sign_type 签名类型,目前仅支持RSA
//5 sign 签名
- (NSString *)generateTradeNO;
@end

//
// Order.m
// AlixPayDemo
//
// Created by 方彬 on 11/2/13.
//
//

#import "Order.h"

@implementation Order

- (NSString *)description {
NSMutableString * discription = [NSMutableStringstring];
if (self.partner) {
[discription appendFormat:@"partner=\"%@\"",self.partner];
}

if (self.seller) {
[discription appendFormat:@"&seller_id=\"%@\"",self.seller];
}
if (self.tradeNO) {
[discription appendFormat:@"&out_trade_no=\"%@\"",self.tradeNO];
}
if (self.productName) {
[discription appendFormat:@"&subject=\"%@\"",self.productName];
}

if (self.productDescription) {
[discription appendFormat:@"&body=\"%@\"",self.productDescription];
}
if (self.amount) {
[discription appendFormat:@"&total_fee=\"%@\"",self.amount];
}
if (self.notifyURL) {
[discription appendFormat:@"¬ify_url=\"%@\"",self.notifyURL];
}

if (self.service) {
[discription appendFormat:@"&service=\"%@\"",self.service];//mobile.securitypay.pay
}
if (self.paymentType) {
[discription appendFormat:@"&payment_type=\"%@\"",self.paymentType];//1
}

if (self.inputCharset) {
[discription appendFormat:@"&_input_charset=\"%@\"",self.inputCharset];//utf-8
}
if (self.itBPay) {
[discription appendFormat:@"&it_b_pay=\"%@\"",self.itBPay];//30m
}
if (self.showUrl) {
[discription appendFormat:@"&show_url=\"%@\"",self.showUrl];//m.alipay.com
}
if (self.rsaDate) {
[discription appendFormat:@"&sign_date=\"%@\"",self.rsaDate];
}
if (self.appID) {
[discription appendFormat:@"&app_id=\"%@\"",self.appID];
}
for (NSString * keyin [self.extraParamsallKeys])
{
[discription appendFormat:@"&%@=\"%@\"", key, [self.extraParamsobjectForKey:key]];
}
return discription;
}

#pragma mark -
#pragma mark ==============产生随机订单号==============

- (NSString *)generateTradeNO
{
staticint kNumber =15;

NSString *sourceStr =@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSMutableString *resultStr = [[NSMutableStringalloc]init];
srand((unsigned)time(0));
for (int i =0; i < kNumber; i++)
{
unsigned index =rand() % [sourceStrlength];
NSString *oneStr = [sourceStrsubstringWithRange:NSMakeRange(index,1)];
[resultStr
appendString:oneStr];
}
return resultStr;
}
@end

-(void)alipayOrder{

Order *order = [[Orderalloc]init];
order.partner =ALIPAY_PID;
order.seller =ALIPAY_SELLER;
order.tradeNO = [ordergenerateTradeNO];

NSMutableString* productName = [NSMutableStringnew];
NSMutableString* productDes = [NSMutableStringnew];
for (NSDictionary *datainself.dataSource)
{
NSDictionary *item = data[SHOPPING_CAR_PRODUCT_INFO];

NSString *productNameStr = [NSStringstringWithFormat:@"%@",
item[SHOPPING_CAR_PRODUCT_INFO_NAME]];
productName = [NSMutableStringstringWithFormat:@"%@,%@", productName, productNameStr];

NSString *productDesStr = [NSStringstringWithFormat:@"%@",
item[SHOPPING_CAR_PRODUCT_INFO_DES]];
productDes = [NSMutableStringstringWithFormat:@"%@;%@", productDes, productDesStr];
}

NSString * subjects = [NSStringstringWithString:productName];
if (productName.length >128) {
//substringToIndex表示从第一个字符串开始截取,到指定长度位置,但是不包括该指定位置位置字符串
subjects = [subjects substringToIndex:128];
//substringFromIndex //表示从指定位置开始截取字符串到最后,所截取位置包含该指定位置
}
subjects = [subjects substringFromIndex:1];//去掉首字符逗号

NSString * bodys = [NSStringstringWithString:productDes];
if (productDes.length >512) {
bodys = [bodys substringToIndex:512];
}
bodys = [bodys substringFromIndex:1];//去掉首字符分号

//商品的标题/交易标题/订单标题/订单关键字等。该参数最长为128个汉字。
order.productName = subjects;
//String(512):对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
order.productDescription = bodys;

//该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。
order.amount =@"0.01";//[NSString stringWithFormat:@"%.2ld",(long)[self computeTotalPrice]];//保留2位小数

order.notifyURL =ALIPAY_NOTIFY_URL;
order.service =@"mobile.securitypay.pay";
order.paymentType =@"1";
order.inputCharset =@"utf-8";
order.itBPay =@"30m";
//应用注册scheme,在Info.plist定义URL types
NSString *appScheme =APPSCHEME;
//将商品信息拼接成字符串
NSString *orderSpec = [orderdescription];
NSLog(@"orderSpec = %@",orderSpec);

//获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
id<DataSigner> signer =CreateRSADataSigner(ALIPAY_PRIVATE_KEY);
NSString *signedString = [signersignString:orderSpec];

//将签名成功字符串格式化为订单字符串,请严格按照该格式
NSString *orderString =nil;
if (signedString !=nil) {
orderString = [NSStringstringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString,
@"RSA"];
NSLog(@"orderString = %@",orderString);
[[AlipaySDKdefaultService]payOrder:orderStringfromScheme:appSchemecallback:^(NSDictionary
*resultDic) {
//【callback处理支付结果】
NSLog(@"reslut = %@",resultDic);

}];
}
}

在RSADataSigner.m文件中 这是支付宝的一大BUG

- (NSString *)formatPrivateKey:(NSString *)privateKey {
constchar *pstr = [privateKeyUTF8String];
int len = (int)[privateKeylength];
NSMutableString *result = [NSMutableStringstring];
[result appendString:@"-----BEGIN RSA PRIVATE KEY-----\n"];
int index =0;
int count =0;
while (index < len) {
char ch = pstr[index];
if (ch =='\r' || ch =='\n')
{
++index;
continue;
}
[result
appendFormat:@"%c", ch];
if (++count ==79)
{
[result
appendString:@"\n"];
count =0;
}
index++;
}
[result appendString:@"\n-----END RSA PRIVATE KEY-----"];
return result;
}

AppDelegate.m中

//- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
//{
// BOOL result = [UMSocialSnsService handleOpenURL:url];
// if (result == FALSE) {
// //调用其他SDK,例如支付宝SDK等
// }
// return result;
//}
//iOS9.0以上(包括iOS9.0),否则在(BOOL)application:(UIApplication *)application openURL:(NSURL
*)url sourceApplication:(NSString *)sourceApplication 中调用
//支付宝同步通知
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*,id>
*)options{
/**
同步通知参数说明
支付宝对商户的请求数据处理完成后,会将处理的结果数据直接通知给商户。这些处理结果数据就是同步通知参数。
同步返回的数据,对于商户在服务端没有收到异步通知的时候,可以依赖服务端对同步返回的结果来进行判断是否支付成功。同步返回的结果中,sign字段描述了请求的原始数据和服务端支付的状态一起拼接的签名信息。验证这个过程包括两个部分:1、原始数据是否跟商户请求支付的原始数据一致(必须验证这个);2、验证这个签名是否能通过。上述1、2通过后,在sign字段中success=true才是可信的。【特别注意,同步结果校验的逻辑,必须放在服务端处理,切记不要放在客户端】【强烈建议商户直接依赖服务端的异步通知,忽略同步返回】

代码示例运行逻辑:
注意:
由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理;
同步返回数据时,建议通过服务端的验签功能代码做验签处理,之后再对返回的数据做业务逻辑处理;
须以服务器异步通知的结果数据为准,并对其做业务逻辑处理;
SDK付款有两种模式:如果外部存在支付宝钱包,则直接跳转到支付宝钱包付款;不存在的场景下,在SDK内部进行H5支付。测试同学需要关注这两类测试场景。
*/

//如果极简开发包不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给开发包
if ([url.hostisEqualToString:@"safepay"])
{
[[AlipaySDKdefaultService]processOrderWithPaymentResult:urlstandbyCallback:^(NSDictionary
*resultDic) {
[selfprocessResult:resultDic];
}];
}
if ([url.hostisEqualToString:@"platformapi"]){//支付宝钱包快登授权返回authCode
[[AlipaySDKdefaultService]processAuthResult:urlstandbyCallback:^(NSDictionary
*resultDic) {
[selfprocessResult:resultDic];
}];
}
returnYES;
}
//支付宝同步通知
-(void)processResult:(NSDictionary *)resultDic{
//【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
NSLog(@"result = %@",resultDic);
//同步返回数据时,建议通过服务端的验签功能代码做验签处理,之后再对返回的数据做业务逻辑处理;
//验签功能代码未写******
NSString* resultStatus = resultDic[@"resultStatus"];
// if ([resultStatus isEqualToString:@"9000"]) {
// //订单支付成功
// UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"订单支付成功" delegate:nil cancelButtonTitle:@"取消"
otherButtonTitles:@"前往", nil];
// [alertView show];
// } else if([resultStatus isEqualToString:@"8000"]){
// //正在处理中
// } else if([resultStatus isEqualToString:@"4000"]){
// //订单支付失败
// } else if([resultStatus isEqualToString:@"6001"]){
// //用户中途取消
// } else if([resultStatus isEqualToString:@"6002"]){
// //网络连接出错
// }

if ([resultStatusisEqualToString:@"9000"]||[resultStatusisEqualToString:@"8000"]||[resultStatusisEqualToString:@"4000"]||[resultStatusisEqualToString:@"6001"]||[resultStatusisEqualToString:@"6002"])
{
//服务器拿异步通知的数据
[KSOrderInterfacebusinessServerQueryOrderPayResultInterFaceWithBusinessTradeNo:@""success:^(AFHTTPRequestOperation
*operation,NSDictionary *param,
id retData) {

NSString* orderStatus = retData[@"list"];
if ([orderStatusisEqualToString:@"WAIT_BUYER_PAY"]) {
//交易创建,等待买家付款。
UIAlertView *alertView = [[UIAlertViewalloc]initWithTitle:@"提示"message:@"等待付款"delegate:selfcancelButtonTitle:@"确定"otherButtonTitles:nil,nil];
[alertView show];

} elseif([orderStatusisEqualToString:@"TRADE_CLOSED"]){
//在指定时间段内未支付时关闭的交易;在交易完成全额退款成功时关闭的交易.
UIAlertView *alertView = [[UIAlertViewalloc]initWithTitle:@"提示"message:@"交易关闭"delegate:selfcancelButtonTitle:@"确定"otherButtonTitles:nil,nil];
[alertView show];
} elseif([orderStatusisEqualToString:@"TRADE_SUCCESS"]){
//交易成功,且可对该交易做操作,如:多级分润、退款等。
UIAlertView *alertView = [[UIAlertViewalloc]initWithTitle:@"提示"message:@"交易成功,可操作"delegate:selfcancelButtonTitle:@"确定"otherButtonTitles:nil,nil];
[alertView show];
} elseif([orderStatusisEqualToString:@"TRADE_FINISHED"]){
//交易成功且结束,即不可再做任何操作。
UIAlertView *alertView = [[UIAlertViewalloc]initWithTitle:@"提示"message:@"交易成功,不可再做任何操作"delegate:selfcancelButtonTitle:@"确定"otherButtonTitles:nil,nil];
[alertView show];
}

} failuer:^(AFHTTPRequestOperation *operation,NSDictionary *param,NSError
*error) {

}];

}
}

Q:

IOS运行时控制台报错 openssl rsa.h file not found 怎么办

A:

需要对“Header Search Paths”增加头文件路径:$(SRCROOT)/项目名称。比如把openssl这个文件导入到了这个工程目录下:项目名称/公共类/工具&第三方/支付宝SDK/openssl ,中间隔了三个文件夹,那么在Header Search Paths 的设置就得改为 $(SRCROOT)/项目名称/公共类/工具&第三方/支付宝SDK,问题就解决了。再

看官方的demo,demo把openssl这个文件放到了项目根目录下,所以“Header Search Paths”只需要设置$(SRCROOT)/项目名称 。

另外切记,demo中使用的rsa.h是为了演示签名的过程,实际签名的过程应该放在服务端。
https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.uDZMU3&treeId=59&articleId=104027&docType=1


注意事项

更新时间:2016/01/06 访问次数:26890

规范点注意事项
签名注意商户在接入的过程中,对于订单的签名行为需发生在服务端(私钥需要妥善保管),切忌将私钥落在客户端进行签名
通知地址通知地址建议走https,确保商户的订单信息不外泄
测试场景商户在测试支付的过程中,需要包括的场景:安装支付宝钱包、无支付宝钱包,并确保两个模式都能支付成功
必看文档:
接入指南 https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.W3JY2K&treeId=58&articleId=103590&docType=1 移动支付 https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.oIYCbS&treeId=59&articleId=103660&docType=1 关于"移动支付"的 热门问题
https://support.open.alipay.com/support/hotProblemDetail.htm?spm=a219a.7386793.0.0.VPK2M2&id=225154&tagId=100199
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: