OC/Swift-支付集成(微信/支付宝)
2019-02-20 本文已影响12人
SK丿希望
一,前期准备,设置URL Types
- 注册微信支付宝这些就不说了
微信设置
identifier:weixin
(可以固定),后面的URL Schemes
为注册微信的appkey
支付宝设置identifier:alipay
(可以固定),后面的URL Schemes
只要唯一就好了
注意:我这里都是固定的,方便后续去info.plist文件里获取数据方便
Swift版
1.创建管理器
import UIKit
private let URLSchemeWechat = "weixin"
private let URLSchemeAlipay = "alipay"
private var successBlock:(()->())?
private var failBlock:((String)->())?
private var appscheme:[String:String] = [:]
enum HWPayType :Int {
case wx = 0
case zfb = 1
}
class wxPayModel : BaseModel { // 注意:这里的模型需要对应后台返回的 不一定是这些 可以对应修改
/// 预支付订单
var prepayid: String?
/// 商家向财付通申请的商家id
var partnerid: String?
/// 商家根据财付通文档填写的数据和签名
var package: String?
/// 随机串,防重发
var noncestr: String?
/// 商家根据微信开放平台文档对数据做的签名
var sign: String?
/// 时间戳,防重发
var timestamp: Int = 0
/// 由用户微信号和AppID组成的唯一标识,发送请求时第三方程序必须填写,用于校验微信用户是否换号登录
var appid: String?
}
class PaymentManage: NSObject {
public static var aliSdkManager:PaymentManage!
/// 获取单例
public static func shared() -> PaymentManage{
PaymentManage.aliSdkManager = PaymentManage.init()
return PaymentManage.aliSdkManager
}
/// 注册支付系统
func registApp(){
let path = Bundle.main.path(forResource: "Info", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
guard let urlTypes:Array<Dictionary<String,Any>> = dict!["CFBundleURLTypes"] as? Array<Dictionary<String,Any>> else {return}
for item in urlTypes {
let urlName = item["CFBundleURLName"] as? String
if let urlSchemes : Array<String> = item["CFBundleURLSchemes"] as? Array<String>{
let urlScheme = urlSchemes.last ?? ""
if urlName! == URLSchemeWechat {
appscheme[URLSchemeWechat] = urlScheme
// 注册微信
WXApi.registerApp(urlScheme)
}else if urlName == URLSchemeAlipay{
// 保存支付宝的
appscheme[URLSchemeAlipay] = urlScheme
}
}
}
}
// 外部用这个方法调起支付支付
func pay(_ type: HWPayType,
request:Any,
paySuccess: @escaping () -> Void,
payFail:@escaping (String) -> Void) {
successBlock = paySuccess
failBlock = payFail
if type == .zfb {
let newrequest = request as! String
AlipaySDK.defaultService().payOrder(newrequest, fromScheme: appscheme[URLSchemeAlipay]) { (result) in }
} else {
if !WXApi.isWXAppInstalled() {//检查一下是否可以使用微信
failBlock!("未安装微信")
HWPrint("未安装微信")
return
} else if !WXApi.isWXAppSupport() {
failBlock!("当前版本微信不支持微信支付")
HWPrint("当前版本微信不支持微信支付")
return
}
let model = request as! wxPayModel
let req = PayReq() // 生成支付模型
req.openID = model.appid
req.partnerId = model.partnerid
req.prepayId = model.prepayid
req.package = model.package
req.timeStamp = UInt32(model.timestamp)
req.nonceStr = model.noncestr
req.sign = model.sign
WXApi.send(req) //调起微信
}
}
func noticeopen(_ url: URL) {
if url.host == "safepay" { // 支付宝
AlipaySDK.defaultService().processOrder(withPaymentResult: url as URL?, standbyCallback: { [weak self]
(resultDic) -> Void in
//调起支付结果处理
self?.showResult(result: resultDic! as NSDictionary);
})
} else if url.host!.contains("pay"){ // 微信
WXApi.handleOpen(url, delegate: self)
}
}
/// 授权回调(这里用的是下一种)
func showAuth_V2Result(result:NSDictionary){
// 9000 请求处理成功
// 4000 系统异常
// 6001 用户中途取消
// 6002 网络连接出错
let returnCode:String = result["resultStatus"] as! String
var returnMsg:String = ""
switch returnCode{
case "6001":
returnMsg = "用户中途取消"
break
case "6002":
returnMsg = "网络连接出错"
break
case "4000":
returnMsg = "系统异常"
break
case "9000":
returnMsg = "授权成功"
break
default:
returnMsg = "系统异常"
break
}
HWPrint(returnMsg)
}
/// 传入回调参数
func showResult(result:NSDictionary){
// 9000 订单支付成功
// 8000 正在处理中
// 4000 订单支付失败
// 6001 用户中途取消
// 6002 网络连接出错
let returnCode:String = result["resultStatus"] as! String
var returnMsg:String = ""
switch returnCode{
case "6001":
returnMsg = "用户中途取消"
if failBlock == nil {return}
failBlock!(returnMsg)
break
case "6002":
returnMsg = "网络连接出错"
if failBlock == nil {return}
failBlock!(returnMsg)
break
case "8000":
returnMsg = "正在处理中"
if failBlock == nil {return}
failBlock!(returnMsg)
break
case "4000":
returnMsg = "订单支付失败"
if failBlock == nil {return}
failBlock!(returnMsg)
break
case "9000":
if successBlock == nil {return}
successBlock!()
returnMsg = "支付成功"
break
default:
returnMsg = "订单支付失败"
if failBlock == nil {return}
failBlock!(returnMsg)
break
}
HWPrint(returnMsg)
}
}
extension PaymentManage : WXApiDelegate {
func onResp(_ resp: BaseResp!) {
if let payressp:PayResp = resp as? PayResp{
switch payressp.errCode{
case 0:
HWPrint("支付成功")
if successBlock == nil {return}
successBlock!()
break
case -1:
HWPrint(resp.errStr)
if failBlock == nil {return}
failBlock!(resp.errStr ?? "")
break
case -2:
HWPrint("用户中途取消")
if failBlock == nil {return}
failBlock!("用户中途取消")
break;
default:
HWPrint("未知错误")
if failBlock == nil {return}
failBlock!("未知错误")
break;
}
}
}
}
2.使用
- 首先需要在
AppDelegate
里didFinishLaunchingWithOptions
方法里进行注册
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
PaymentManage.shared().registApp() // 注册支付管理者
return true
}
- 其次收到回调信息后通知管理者进行回调
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let result = UMSocialManager.default().handleOpen(url, sourceApplication: sourceApplication, annotation: annotation)
if (!result) {
// 其他如支付等SDK的回调
PaymentManage.shared().noticeopen(url)
}
return result;
}
- 最后就是使用了
例如:当前是微信支付
if type == .wx {
// 网络请求对应的支付信息 转成模型 <注意模型要转成wxPayModel类型,因为内部用这个类型处理事件的>
PaymentManage.shared().pay(.wx, request: model , paySuccess: {
/// 支付成功要做的事
}, payFail: { (error) in
///error 支付失败的信息
})
} else {
支付宝就直接把json数据传入进去就好了
}
OC版
1.创建管理者
- .h文件
#import <Foundation/Foundation.h>
#define DWQWECHATURLNAME @"weixin"
#define DWQALIPAYURLNAME @"alipay"
NS_ASSUME_NONNULL_BEGIN
@interface HWPayWXModel : NSObject
@property (nonatomic, copy) NSString *prepayid;
@property (nonatomic, copy) NSString *partnerid;
@property (nonatomic, copy) NSString *package;
@property (nonatomic, copy) NSString *noncestr;
@property (nonatomic, assign) UInt32 timestamp;
@property (nonatomic, copy) NSString *sign;
@property (nonatomic, copy) NSString *appid;
@end
@interface HWPayManage : NSObject
/** 单例管理 */
+ (instancetype)shareManager;
/** 注册 */
- (void)hw_registerApp;
/** 支付 */
- (void)hw_payWithOrderMessage:(id)orderMessage success:(void(^)(void))success fail:(void(^)(NSString *error))fail;
/** 收到回调后接收通知 */
- (BOOL)hw_handleUrl:(NSURL *)url;
@end
NS_ASSUME_NONNULL_END
- .m文件
#import "HWPayManage.h"
#import <WXApi.h>
#import <AlipaySDK/AlipaySDK.h>
// 回调url地址为空
#define DWQTIP_CALLBACKURL @"url地址不能为空!"
// 订单信息为空字符串或者nil
#define DWQTIP_ORDERMESSAGE @"订单信息不能为空!"
// 没添加 URL Types
#define DWQTIP_URLTYPE @"请先在Info.plist 添加 URL Type"
// 添加了 URL Types 但信息不全
#define DWQTIP_URLTYPE_SCHEME(name) [NSString stringWithFormat:@"请先在Info.plist 的 URL Type 添加 %@ 对应的 URL Scheme",name]
@implementation HWPayWXModel
@end
@interface HWPayManage ()<WXApiDelegate>
// 缓存appScheme
@property (nonatomic,strong)NSMutableDictionary *appSchemeDict;
/** <#注释#> */
@property(nonatomic, copy) void(^successBlock)(void);
/** <#注释#> */
@property(nonatomic, copy) void(^failBlock)(NSString *error);
@end
@implementation HWPayManage
+ (instancetype)shareManager{
static HWPayManage *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (void)hw_registerApp {
NSString *path = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *urlTypes = dict[@"CFBundleURLTypes"];
NSAssert(urlTypes, DWQTIP_URLTYPE);
for (NSDictionary *urlTypeDict in urlTypes) {
NSString *urlName = urlTypeDict[@"CFBundleURLName"];
NSArray *urlSchemes = urlTypeDict[@"CFBundleURLSchemes"];
NSAssert(urlSchemes.count, DWQTIP_URLTYPE_SCHEME(urlName));
// 一般对应只有一个
NSString *urlScheme = urlSchemes.lastObject;
if ([urlName isEqualToString:DWQWECHATURLNAME]) {
[self.appSchemeDict setValue:urlScheme forKey:DWQWECHATURLNAME];
// 注册微信
[WXApi registerApp:urlScheme];
} else if ([urlName isEqualToString:DWQALIPAYURLNAME]){
// 保存支付宝scheme,以便发起支付使用
[self.appSchemeDict setValue:urlScheme forKey:DWQALIPAYURLNAME];
}
}
}
- (void)hw_payWithOrderMessage:(id)orderMessage success:(void(^)(void))success fail:(void(^)(NSString *error))fail {
self.successBlock = success;
self.failBlock = fail;
if (orderMessage[@"info"]) { // 支付宝支付
[[AlipaySDK defaultService] payOrder:orderMessage[@"info"] fromScheme:self.appSchemeDict[DWQALIPAYURLNAME] callback:^(NSDictionary *resultDic) {}];
} else { // 微信支付
if (![WXApi isWXAppInstalled]) { // 没有安装微信
self.failBlock(@"没有安装微信");
return;
}
if (![WXApi isWXAppSupportApi]) { // 当前版本微信不支持微信支付
self.failBlock(@"当前版本微信不支持微信支付");
return;
}
HWPayWXModel *model = [HWPayWXModel mj_objectWithKeyValues:orderMessage];
PayReq *payReq = [[PayReq alloc] init];
payReq.partnerId = model.partnerid;
payReq.prepayId = model.prepayid;
payReq.nonceStr = model.noncestr;
payReq.timeStamp = model.timestamp;
payReq.package = model.package;
payReq.sign = model.sign;
payReq.openID = model.appid;
[WXApi sendReq:payReq];
}
}
- (BOOL)hw_handleUrl:(NSURL *)url {
NSAssert(url, DWQTIP_CALLBACKURL);
if ([url.host isEqualToString:@"pay"]) {// 微信
return [WXApi handleOpenURL:url delegate:self];
} else if ([url.host isEqualToString:@"safepay"]) {// 支付宝
__weak typeof(self) weakSelf = self;
// 支付跳转支付宝钱包进行支付,处理支付结果(在app被杀模式下,通过这个方法获取支付结果)
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
[weakSelf showResult:resultDic];
}];
return YES;
} else{
return NO;
}
}
- (void)showResult:(NSDictionary *)resultDic {
NSString *resultStatus = resultDic[@"resultStatus"];
if ([resultStatus isEqualToString:@"6001"]) {
self.failBlock(@"用户中途取消");
} else if ([resultStatus isEqualToString:@"6002"]) {
self.failBlock(@"网络连接出错");
} else if ([resultStatus isEqualToString:@"8000"]) {
self.failBlock(@"正在处理中");
} else if ([resultStatus isEqualToString:@"4000"]) {
self.failBlock(@"订单支付失败");
} else if ([resultStatus isEqualToString:@"9000"]) {
self.successBlock();
} else {
self.failBlock(@"订单支付失败");
}
}
#pragma mark - WXApiDelegate
- (void)onResp:(BaseResp *)resp {
// 判断支付类型
if([resp isKindOfClass:[PayResp class]]){
//支付回调
NSString *errStr = resp.errStr;
switch (resp.errCode) {
case 0:
self.successBlock();
errStr = @"订单支付成功";
break;
case -1:
errStr = resp.errStr;
self.failBlock(errStr);
break;
case -2:
errStr = @"用户中途取消";
self.failBlock(errStr);
break;
default:
errStr = resp.errStr;
self.failBlock(errStr);
break;
}
}
}
- (NSMutableDictionary *)appSchemeDict{
if (_appSchemeDict == nil) {
_appSchemeDict = [NSMutableDictionary dictionary];
}
return _appSchemeDict;
}
@end
2.使用
- 在
AppDelegate
的didFinishLaunchingWithOptions
方法中注册
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[HWPayManage shareManager] hw_registerApp];
return YES;
}
- 收到回调后通知管理者
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url];
if (!result) {
// 其他如支付等SDK的回调
return [[HWPayManage shareManager] hw_handleUrl:url];
}
return result;
}
- 使用 (注意这里没有提供类型选择, 是根据后台返回的json字段中是否有
info
来判断的)
[[HWPayManage shareManager] hw_payWithOrderMessage:item.data success:^{
/// 支付成功处理逻辑
} fail:^(NSString * _Nonnull error) {
/// 支付失败处理逻辑
}];
总结:如果有分享需要注意,收到回调方法可能会被覆盖这样就收不到支付信息的回调了,需要注意
代码