Demo
Demo下載地址
demo使用時,請在WTPayKeys.h里面將各個參數(shù)配置好!!!!
一. 微信支付
1.所需要的材料
- 微信SDK
微信SDK - 在微信開放平臺上面申請得到的參數(shù)
// 應用的APPID
kWXAppID @"wxc82cXXXXXXXX"
// AppSecret
kWXAppSecret @"7f47bfe47b84XXXXXXXXXXXx"
//商戶號
kWXMchID @"1242XXXXXX"
//商戶API密鑰
kWXPartnerID @"n1LeHtXUV9ZuPp156mcmXXXXXXXXX"
//支付結果回調(diào)頁面
kWXNotifyURL @"http://XXXXXXXXX"
1.2 微信支付工程配置
// 需要的系統(tǒng)依賴
SystemConfiguration.framework
libz.dylib
libsqlite3.0.dylib
libc++.dylib
2.調(diào)起微信客戶端代碼
[WXApi registerApp:weichat_appid];
//調(diào)起微信支付
PayReq* req = [[PayReq alloc] init];
req.partnerId = item.partnerid;
req.prepayId = item.prepayid;
req.nonceStr = item.noncestr;
req.timeStamp = [item.timestamp intValue];
req.package = item.package;
req.sign = item.sign;
[WXApi sendReq:req];
問: 微信支付怎么支付?
答: 其實就是上面的代碼.
- 創(chuàng)建一個PayReq對象req, 然后[WXApi sendReq:req]; 就這么簡單.
難就難在,怎么得到PayReq對象所需要的那些值,一共六個值.
而這六個值其他的值好說,就兩個:prepayId和sign比較麻煩. - 獲取prepayId(預支付訂單)是需要發(fā)請求給微信(統(tǒng)一下單),然后微信返回結果給我們的.
- 而sign前面的話,各種參數(shù)柔和在一起,MD5一下,也比較煩.
3.拿到prepayId
怎么拿?
官方文檔---->統(tǒng)一下單
就是發(fā)一個請求給微信,然后微信返回prepayId給你.官方要求統(tǒng)一下單要放在我們的服務器做.--------這是個好事情!!!!!!!!!!!
服務器端完成的!!!!哈哈哈哈,其實放在服務器端做的話,接入微信支付就沒什么好說的了.
- 放在服務器端我們的步奏
- 拿到商品id 和 商品名稱 商品價格發(fā)給我們的服務器,然后服務器端返回給我們調(diào)用微信需要的PayReq對象req的所有參數(shù)
- 我們調(diào)起微信(沒錯現(xiàn)實當中就是這樣的簡單,我們發(fā)個請求,服務端給我需要的所有參數(shù),然后我們調(diào)起微信就ok, 煩不了~)
統(tǒng)一下單API、支付結果通知API和查詢訂單API等都涉及簽名過程,調(diào)用都必須在商戶服務器端完成。
其實不用服務端,我們也可以完成. 就是我們自己發(fā)請求然后拿到prepayId,我只是說我們自己可以做,但是現(xiàn)實中我們應當放在服務端,官方文檔就是這么要求,這樣我們省了好多事的好不,接入微信就很簡單了.</br>
但是為了演示效果,而又沒有現(xiàn)成的服務器接口給我們.所以Demo中,我是將說有過程寫在我們本地.
放在我們本地的做法
1.我們想這個接口:@"https://api.mch.weixin.qq.com/pay/unifiedorder" 發(fā)一個post請求
2.參數(shù)
aped //開放平臺appid
mch_id //商戶號
nonce_str//隨機串
trade_type //支付類型,固定為APP
body //訂單描述,展示給用戶, 就是商品名
notify_url //支付結果異步通知, 就是kWXNotifyURL
out_trade_no //商戶訂單號 我們自己設定的訂單號
spbill_create_ip // //發(fā)器支付的機器ip
total_fee //訂單金額,單位為分
sign // 簽名, 就是上面那些參數(shù)按照字母順序拼接成一個字符串,然后再拼接一個kWXPartnerID . 有關sign(簽名)的生成可以參考官方文檔,或者看下面關于sign的"通俗說法",或者直接看Demo
4.partnerId 商家向財付通申請的商家id
// 商家向財付通申請的商家id 這個不用說, 自己去微信開放平臺上拿
5.nonceStr 隨機串
/**
* 生成隨機字符串
*
* @param kNumber 訂單號的長度
*/
- (NSString *)generateRomNumWithNumber: (NSInteger)kNumber
{
NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSMutableString *resultStr = [[NSMutableString alloc] init];
srand((unsigned int)time(0));
for (NSInteger i = 0; i < kNumber; i++)
{
unsigned index = rand() % [sourceStr length];
NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
[resultStr appendString:oneStr];
}
return resultStr;
}
6.timeStamp 時間戳
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@"%ld", now];
7.package 商家根據(jù)財付通文檔填寫的數(shù)據(jù)和簽名
這個是個死值 Sign=WXPay
官方文檔說:暫填寫固定值Sign=WXPay
8.sign
官方文檔這么說的</br>
簽名算法
簽名生成的通用步驟如下:
第一步,設所有發(fā)送或者接收到的數(shù)據(jù)為集合M,將集合M內(nèi)非空參數(shù)值的參數(shù)按照參數(shù)名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特別注意以下重要規(guī)則:
◆ 參數(shù)名ASCII碼從小到大排序(字典序);
◆ 如果參數(shù)的值為空不參與簽名;
◆ 參數(shù)名區(qū)分大小寫;
◆ 驗證調(diào)用返回或微信主動通知簽名時,傳送的sign參數(shù)不參與簽名,將生成的簽名與該sign值作校驗。
◆ 微信接口可能增加字段,驗證簽名時必須支持增加的擴展字段
第二步,在stringA最后拼接上key得到stringSignTemp字符串,并對stringSignTemp進行MD5運算,再將得到的字符串所有字符轉換為大寫,得到sign值signValue。
通俗的說:
1.就是拿到PayReq對象的其他5個值,參數(shù)名ASCII碼從小到大排序(字典序),然后
a字母順序第一個appid,就是第一,然后后面的同樣按照字母先后順序一個&一個那么拼接成一個字符串.
str1 = @"appid=wxd930ea5d5a258f4f&package=Sign=WXPay......";
2.得到上面的字符串以后了再在后的字符串后面拼接上key
// kWXPartnerID @"n1LeHtXUV9ZuPp156mcmXXXXXXXXX"
str2 = [str1 appendFormat:@"key=%@", kWXPartnerID];
然后對str2 MD5加密一下,就得到了sign了.
如果是按照官方文檔"統(tǒng)一下單API、支付結果通知API和查詢訂單API等都涉及簽名過程,調(diào)用都必須在商戶服務器端完成。"這樣,上面的這些所有參數(shù)你都不用管,你要做的只是,拿到你們APP里面商品的價格,商品名什么的發(fā)給后臺,然后后臺就會把你需要的這些所有參數(shù)給你,然后你拿著這些參數(shù)調(diào)起微信就ok!
</br></br>
二.支付寶支付
1.需要的材料
支付寶SDK
下載下來解壓文件如圖
// 解壓iOS那個zip
// 得到如圖
// 我們需要的文件有如圖
// 在我們工程里面新建一個文件夾Alipay將上面我們需要的文件放在文件Alipay下
// 支付寶需要的系統(tǒng)庫
"1"CFNetwork.framework
"2"CoreMotion.framework
"3"“SystemConfiguration.framework”,
"4"“CoreGraphics.Framework”、
"5"“CoreTelephony.framework”
"6"“l(fā)ibz.dylib”
"7"libc++.dylib
"8"QuartzCore.framework
"9"CoreText.framework
// 在支付寶上申請得到的參數(shù)
#ifndef __OPTIMIZE__
#define kPayNotifyURL @"http://WWW.XXXX.XXXXXXXXX"
#else
#define kPayNotifyURL @"https://WWW.FFFF.XXXXXXX"
#endif
#define kPrivateKey @"SDGSFHGDFHGSVF$%#$RFFDSFASFASFASFSDFASDFASDCVCVZXVZXCVZXCVZXCVXCVZXCVGQWY%##$T@!RXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"http://
#define kSeller @"20XXXXXXXXXXXXXX"
#define kPartner @"20XXXXXXXXXXXXX"
kPayNotifyURL
kPrivateKey
kSeller
kPartner
2.支付實現(xiàn)
我是用WTPayManager統(tǒng)一管理微信和支付寶支付的
在WTPayManager里包含
import <AlipaySDK/AlipaySDK.h>
調(diào)用支付寶代碼
+ (void)aliPayWithOrderItem:(WTPayOrderItem *)orderItem
{
/*
*商戶的唯一的parnter和seller。
*簽約后,支付寶會為每個商戶分配一個唯一的 parnter 和 seller。
*/
/*
*生成訂單信息及簽名
*/
//將商品信息賦予AlixPayOrder的成員變量
Order *order = [[Order alloc] init];
order.partner = kPartner;
order.sellerID = kSeller;
order.outTradeNO = orderItem.orderOutTradeNO;//訂單ID(由商家自行制定)
order.subject = orderItem.orderName;//商品標題
order.body = orderItem.orderBody; //商品描述
order.totalFee = orderItem.orderPrice; //商品價格
order.notifyURL = kPayNotifyURL;
order.service = @"mobile.securitypay.pay";//接口名稱,固定為mobile.securitypay.pay。
order.paymentType = @"1";
order.inputCharset = @"utf-8";
order.itBPay = @"30m";
order.showURL = @"m.alipay.com";
//應用注冊scheme,在AlixPayDemo-Info.plist定義URL types
NSString *appScheme = @"XXXXXXXXXX";
//將商品信息拼接成字符串
NSString *orderSpec = [order description];
NSLog(@"orderSpec = %@",orderSpec);
//獲取私鑰并將商戶信息簽名,外部商戶可以根據(jù)情況存放私鑰和簽名,只需要遵循RSA簽名規(guī)范,并將簽名字符串base64編碼和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(kPrivateKey);
NSString *signedString = [signer signString:orderSpec];
//將簽名成功字符串格式化為訂單字符串,請嚴格按照該格式
// __weak typeof(self) weakSelf = self;
NSString *orderString = nil;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
NSLog(@"resultDic=%@",resultDic);
//[weakSelf handleAlipayResponse:resultDic];
}];
}else{
//[self handleAlipayResponse:nil];
}
}
// 支付寶支付相對微信來說簡單些
拿到
kPayNotifyURL
kPrivateKey
kSeller
kPartner
這幾個參數(shù)
加上我們的商品價格,名稱,商品訂單,本地加個密,往支付寶一推,就ok了.
集成支付寶openssl可能會出現(xiàn)
導入SDK或者調(diào)用支付寶失敗的情況
1.0 openssl/asn1.h file not found
點擊這里答案,感謝-----荏苒少年
三.統(tǒng)一配置
info.plist // 文件下加入這個
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sinaweibohd</string>
<string>sinaweibo</string>
<string>sinaweibosso</string>
<string>weibosdk</string>
<string>weibosdk2.5</string>
<string>mqqapi</string>
<string>mqq</string>
<string>mqqOpensdkSSoLogin</string>
<string>mqqconnect</string>
<string>mqqopensdkdataline</string>
<string>mqqopensdkgrouptribeshare</string>
<string>mqqopensdkfriend</string>
<string>mqqopensdkapi</string>
<string>mqqopensdkapiV2</string>
<string>mqqopensdkapiV3</string>
<string>mqzoneopensdk</string>
<string>wtloginmqq</string>
<string>wtloginmqq2</string>
<string>mqqwpa</string>
<string>mqzone</string>
<string>mqzonev2</string>
<string>mqzoneshare</string>
<string>wtloginqzone</string>
<string>mqzonewx</string>
<string>mqzoneopensdkapiV2</string>
<string>mqzoneopensdkapi19</string>
<string>mqzoneopensdkapi</string>
<string>mqzoneopensdk</string>
<string>alipay</string>
<string>alipayshare</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
// PCH
// -ObjC
// URL Schemes
四. WTPayManager 代碼實現(xiàn)
WTPayManager.h
//
// WTPayManager.h
// WT_Pay
//
// Created by Mac on 16/7/5.
// Copyright ? 2016年 wutong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AlipaySDK/AlipaySDK.h>
#import "WXApi.h"
@interface WTPayOrderItem : NSObject
/**
商品名稱
*/
@property (nonatomic, strong)NSString * orderName;
/**
商品價格
支付寶的單位是元
微信的單位是分
*/
@property (nonatomic, strong)NSString * orderPrice;
/**
訂單號
*/
@property (nonatomic, strong)NSString * orderOutTradeNO;
/**
商品描述
*/
@property (nonatomic, strong)NSString * orderBody;
@end
typedef NS_ENUM(NSInteger, WTPayType) {
WTPayTypeAli = 0, // 支付寶支付
WTPayTypeWeixin // 微信支付
};
typedef NS_ENUM(NSInteger, WTPayAilPayResultType) {
WTPayAilPayResultTypeSucess = 9000, // 支付成功
WTPayAilPayResultTypeCancel = 6001// 用戶取消
};
typedef void(^WTPayResultBlock)(NSDictionary * payResult, NSString * error);
@interface WTPayManager : NSObject<WXApiDelegate>
+ (instancetype)shareWTPayManager;
- (void)handleAlipayResponse:(NSDictionary *)resultDic;
+ (void)wtPayOrderItem:(WTPayOrderItem *)orderItem payType:(WTPayType)type result:(WTPayResultBlock)result;
@end
WTPayManager.m
//
// WTPayManager.m
// WT_Pay
//
// Created by Mac on 16/7/5.
// Copyright ? 2016年 wutong. All rights reserved.
//
#import "WTPayManager.h"
#import "payRequsestHandler.h"
#import "Order.h"
#import "DataSigner.h"
@interface WTPayManager ()<NSCopying>
@property (nonatomic, copy)WTPayResultBlock result;
@end
@implementation WTPayManager
+ (void)initialize
{
[WTPayManager shareWTPayManager];
}
static WTPayManager * _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
[_instance setRegisterApps];
});
return _instance;
}
+ (instancetype)shareWTPayManager
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc]init];
[_instance setRegisterApps];
});
return _instance;
}
- (id)copyWithZone:(nullable NSZone *)zone
{
return _instance;
}
// 注冊appid
- (void)setRegisterApps
{ // 微信注冊
[WXApi registerApp:kWXAppID];
}
+ (void)wtPayOrderItem:(WTPayOrderItem *)orderItem payType:(WTPayType)type result:(WTPayResultBlock)result
{
[WTPayManager shareWTPayManager].result = result;
if (type == WTPayTypeWeixin) {
[WTPayManager weixinPayWithOrderItem:orderItem];
}else if (type == WTPayTypeAli){
[WTPayManager aliPayWithOrderItem:orderItem];
}
}
+ (void)aliPayWithOrderItem:(WTPayOrderItem *)orderItem
{
/*
*商戶的唯一的parnter和seller。
*簽約后,支付寶會為每個商戶分配一個唯一的 parnter 和 seller。
*/
/*
*生成訂單信息及簽名
*/
//將商品信息賦予AlixPayOrder的成員變量
Order *order = [[Order alloc] init];
order.partner = kPartner;
order.sellerID = kSeller;
order.outTradeNO = orderItem.orderOutTradeNO;//訂單ID(由商家自行制定)
order.subject = orderItem.orderName;//商品標題
order.body = orderItem.orderBody; //商品描述
order.totalFee = orderItem.orderPrice; //商品價格
order.notifyURL = kPayNotifyURL;
order.service = @"mobile.securitypay.pay";
order.paymentType = @"1";
order.inputCharset = @"utf-8";
order.itBPay = @"30m";
order.showURL = @"m.alipay.com";
//應用注冊scheme,在AlixPayDemo-Info.plist定義URL types
NSString *appScheme = @"mralipaysdk";
//將商品信息拼接成字符串
NSString *orderSpec = [order description];
NSLog(@"orderSpec = %@",orderSpec);
//獲取私鑰并將商戶信息簽名,外部商戶可以根據(jù)情況存放私鑰和簽名,只需要遵循RSA簽名規(guī)范,并將簽名字符串base64編碼和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(kPrivateKey);
NSString *signedString = [signer signString:orderSpec];
//將簽名成功字符串格式化為訂單字符串,請嚴格按照該格式
// __weak typeof(self) weakSelf = self;
NSString *orderString = nil;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
NSLog(@"resultDic=%@",resultDic);
//[weakSelf handleAlipayResponse:resultDic];
}];
}else{
//[self handleAlipayResponse:nil];
}
}
- (void)handleAlipayResponse:(NSDictionary *)resultDic
{
// resultDic;
NSLog(@"%@", resultDic);
if ([resultDic[@"resultStatus"] integerValue] != WTPayAilPayResultTypeSucess) {
NSString * errorStr;
errorStr = resultDic[@"memo"] ? resultDic[@"memo"] : @"支付失敗";
self.result(nil, errorStr);
}else{
NSDictionary * response = @{@"result":@"支付寶支付成功!"};
self.result(response,nil);
}
}
+ (void)weixinPayWithOrderItem:(WTPayOrderItem *)orderItem
{
payRequsestHandler *payObj = [payRequsestHandler sharedInstance];
//1. 拿到prepayId 和 sign, 其他參數(shù)寫在外面都行
NSDictionary * dict = [payObj sendPay:orderItem.orderName orderPrice:orderItem.orderPrice outTradeNo:orderItem.orderOutTradeNO];
// 2.調(diào)起微信支付
if(dict != nil){
NSMutableString *retcode = [dict objectForKey:@"retcode"];
if (retcode.intValue == 0){
NSMutableString *stamp = [dict objectForKey:@"timestamp"];
//調(diào)起微信支付
PayReq* req = [[PayReq alloc] init];
req.partnerId = [dict objectForKey:@"partnerid"];
req.prepayId = [dict objectForKey:@"prepayid"];
req.nonceStr = [dict objectForKey:@"noncestr"];
req.timeStamp = stamp.intValue;
req.package = [dict objectForKey:@"package"];
req.sign = [dict objectForKey:@"sign"];
BOOL success = [WXApi sendReq:req];
if(!success){
NSLog(@"調(diào)微信失敗");
}
return;
}else{
NSLog(@"%@",[dict objectForKey:@"retmsg"]);
}
}else{
NSLog(@"服務器返回錯誤");
}
}
-(void)onResp:(BaseResp*)resp{
if ([resp isKindOfClass:[PayResp class]]){
PayResp*response=(PayResp*)resp;
if (response.errCode == WXSuccess) {
NSDictionary * response = @{@"result":@"微信支付成功!"};
self.result(response,nil);
}else{
NSLog(@"支付失敗,retcode=%d",resp.errCode);
self.result(nil,@"支付失敗");
}
}
}
@end
@implementation WTPayOrderItem
@end
Demo
Demo下載地址
demo使用時,請在WTPayKeys.h里面將各個參數(shù)配置好!!!!