公司須要到微信開放品臺進行申請app支付功能 , 得到appid和微信支付商戶號(mch_id)和API祕鑰(key) 、 Appsecret(secret),開發中用到的,很重要html
• appid:appid是微信公衆帳號或開放平臺APP的惟一標識,在公衆平臺申請公衆帳號或者在開放平臺申請APP帳號後,微信會自動分配對應的appid,用於標識該應用。可json
在微信公衆平臺-->開發者中心查看,商戶的微信支付審覈經過郵件中也會包含該字段值。安全
• 微信支付商戶號:商戶申請微信支付後,由微信支付分配的商戶收款帳號。服務器
• API密鑰: 交易過程生成簽名的密鑰,僅保留在商戶系統和微信支付後臺,不會在網絡中傳播。商戶妥善保管該Key,切勿在網絡中傳輸,不能在其餘客戶端中存儲,保證微信
key不會被泄漏。商戶可根據郵件提示登陸微信商戶平臺進行設置。也可按一下路徑設置:微信商戶平臺(pay.weixin.qq.com)-->帳戶設置-->API安全-->密鑰設置網絡
• App secret : AppSecret是APPID對應的接口密碼,用於獲取接口調用憑證access_token時使用。微信開發
項目-->Info-->RUL Types,添加一個URL SChemes,內容爲本身商戶的APPID,以下圖:app
步驟1:用戶在商戶APP中選擇商品,提交訂單,選擇微信支付。微信公衆平臺
步驟2:商戶後臺收到用戶支付單,調用微信支付統一下單接口。ide
步驟3:統一下單接口返回正常的prepay_id,再按簽名規範從新生成簽名後,將數據傳輸給APP。參與簽名的字段名爲appId,partnerId,prepayId,nonceStr,timeStamp,package。
注意:package的值格式爲Sign=WXPay
步驟4:商戶APP調起微信支付。
步驟5:商戶後臺接收支付通知。
步驟6:商戶後臺查詢支付結果。
請求後臺接口,獲取調取微信支付所需的關鍵參數:partnerid、prepayid、package、sign、timestamp、noncestr
[WXApi registerApp:self.wxAppID];//與URL Type中設置的保持一致
request.openID = self.wxAppKey; request.partnerId = parterId; request.prepayId = prePayId; request.package = package; request.nonceStr = nonceStr; request.timeStamp = [timestamp intValue]; request.sign = sign;
if (![WXApi sendReq:request]) {
//微信調起支付失敗
}
-(void)onResp:(BaseResp*)resp{ if ([respisKindOfClass:[PayRespclass]]){ PayResp*response=(PayResp*)resp; switch(response.errCode){ caseWXSuccess: //服務器端查詢支付通知或查詢API返回的結果再提示成功 NSlog(@"支付成功"); break; default: NSlog(@"支付失敗,retcode=%d",resp.errCode); break; } } }
這裏設置的URL Scheme必須與payOrder方法中的Scheme保持一致
在info.plist 文件中以下設置
這一步能夠經過後臺生成訂單,直接返回訂單字符串,或者移動端本身實例化一個訂單對象,並生成訂單字符串
//將商品信息賦予AlixPayOrder的成員變量 Order *order = [[Order alloc] init]; order.partner = partner; order.seller = seller; order.tradeNO = @"123456"; //訂單ID(由商家自行制定) order.productName = @"太空杯"; //商品標題 order.productDescription = @"耐摔的太空杯"; //商品描述 order.amount = [NSString stringWithFormat:@"%.2f",0.01]; //商品價格 order.notifyURL = @"http://www.lanou3g.com"; //回調URL 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 = @"xiaohange"; //將商品信息拼接成字符串 NSString *orderSpec = [order description]; NSLog(@"orderSpec = %@",orderSpec); //獲取私鑰並將商戶信息簽名,外部商戶能夠根據狀況存放私鑰和簽名,只須要遵循RSA簽名規範,並將簽名字符串base64編碼和UrlEncode id<DataSigner> signer = CreateRSADataSigner(privateKey); NSString *signedString = [signer signString:orderSpec]; //將簽名成功字符串格式化爲訂單字符串,請嚴格按照該格式 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(@"reslut = %@",resultDic); //}]; }
b.調起支付寶支付
[[AlipaySDK defaultService] payOrder:orderString fromScheme:@"669SDKAliPay" callback:^(NSDictionary *dict) { if (dict) { NSLog(@"%@",dict); NSInteger statusCode = [dict[@"resultStatus"] integerValue]; NSString *msg = [NSString stringValue:dict[@"memo"]]; if (statusCode == 9000) { [self performSelector:@selector(paymentSuccess) withObject:self.tradeNo afterDelay:0.25f]; } else if (statusCode == 6001) { [self performSelector:@selector(paymentCancel) withObject:self.tradeNo afterDelay:0.25f]; } else { [self performSelector:@selector(paymentErrorWithMessage:) withObject:msg afterDelay:0.25f]; } } }];
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import "WXApi.h" #import <AlipaySDK/AlipaySDK.h> @protocol WanPaymentDataDelegate <NSObject> @optional - (void)paymentSuccess; - (void)paymentCancel; - (void)paymentResultWithError:(NSError *)error; @end typedef NS_OPTIONS(NSUInteger, WanPaymentType) { WanPaymentTypeAliPay = 2, //支付寶錢包 WanPaymentTypeWXPay = 1, //微信支付 WanPaymentTypeAliPayWAP = 102 //支付寶 WAP }; @interface WanPaymentData : NSObject <WXApiDelegate> { } @property (nonatomic, assign) WanPaymentType paymentType; @property (nonatomic, weak) id<WanPaymentDataDelegate> delegate; @property (nonatomic, weak) UIView *view; @property (nonatomic, copy) NSString *wxAppKey; @property (nonatomic, retain) NSString *tradeNo; //訂單編號 @property (nonatomic, retain) NSString *paymentTradeNo; //支付編號 - 支付寶給的 @property (nonatomic, retain) NSString *productName; //訂單名稱 @property (nonatomic, retain) NSString *productDesc; //訂單描述 @property (nonatomic, retain) NSString *productAmount; //訂單單價 @property (nonatomic, retain) NSString *productEndTime; //訂單結束時間 + (instancetype)instance; + (BOOL)canOpenPaymentApp:(WanPaymentType)paymentType; - (void)requestPaymentURLWithResult:(NSDictionary *)dict; - (void)paymentErrorWithMessage:(NSString *)errorMessage; - (BOOL)handleOpenURL:(NSURL *)url; //支付寶客戶端回調 - (void)wxpayResultCode:(int)resultCode; //微信支付客戶端回調 @end
#import "WanPaymentData.h" #import "NSString+Util.h" #import "AlixPayResult.h" //#import "PPUIUtils.h" //#import "UPPayPlugin.h" #import <YRJSONAdapter.h> #import "WanPayServer.h" #import "WanProgressHUD.h" static NSString *kPPPaymentURLForAliPay = @"alipay://alipayclient/"; static NSString *kPPGetPaymentURL = @"payment-pay/paySubmit"; static NSString *kPPPaymentParamAliPayClient = @"alipay_sdk"; //支付寶錢包 static NSString *kPPPaymentParamAliPayWAP = @"alipay_wap"; //支付寶網頁 static NSString *kPPPaymentParamWXPayClient = @"wechat_sdk"; //微信客戶端 #define kWeiXinWanAppKey @"wxb68956c81f8a2512" typedef NS_OPTIONS(NSUInteger, PPPaymentWCheckStatus) { PPPaymentCheckStatusOK = 1, //能夠支付 PPPaymentCheckStatusAppNotInstalled = 2, //應用未安裝 PPPaymentCheckStatusSignError = 3 //簽名錯誤 }; @interface WanPaymentData () { WanPayServer *_payServer; } @end @implementation WanPaymentData + (instancetype)instance { static WanPaymentData *sharedInstance = nil; if (sharedInstance == nil) { sharedInstance = [[WanPaymentData alloc] init]; } return sharedInstance; } #pragma mark - Init #pragma mark - Class Method + (BOOL)canOpenPaymentApp:(WanPaymentType)paymentType { if (paymentType == WanPaymentTypeAliPay) { return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:kPPPaymentURLForAliPay]]; } else if (paymentType == WanPaymentTypeWXPay) { return [WXApi isWXAppInstalled]; } return NO; } #pragma mark - Request Payment URL - (void)requestPaymentURLWithResult:(NSDictionary *)dict { [WanProgressHUD hideAfterDelay:1.5]; NSInteger resultCode = [[NSString stringValue:dict[@"state"][@"code"]] integerValue]; NSString *resultMsg = [NSString stringValue:dict[@"state"][@"msg"]]; if (resultCode == 1) { if (self.paymentType == WanPaymentTypeAliPay) { NSString *paymentURL = [NSString stringValue:dict[@"data"][@"pay_info"]]; NSString *clientFlag = [NSString stringValue:dict[@"data"][@"order_no"]]; [self openAliPayClientWithPaymentURL:paymentURL clientFlag:clientFlag]; } else if (self.paymentType == WanPaymentTypeAliPayWAP) { NSString *paymentURL = [NSString stringValue:[dict valueForKeyPath:@"data.payment_url"]]; NSString *htmlCode = [NSString stringValue:[dict valueForKeyPath:@"data.payment_html"]]; NSDictionary *param = @{@"title" : @"支付寶網頁支付", @"URL" : paymentURL, @"html" : htmlCode}; // [[NSNotificationCenter defaultCenter] postNotificationName:LMBNotificationKeyForShowPaymentWebPage object:param userInfo:nil]; } else if (self.paymentType == WanPaymentTypeWXPay) { // NSString *jsonString = [NSString stringValue:[dict valueForKeyPath:@"data.payment_wx"]]; // NSDictionary *param = [jsonString objectFromJSONString]; [self openWXClientWithPaymentURL:dict[@"data"][@"pay_info"]]; } }else{ [self paymentErrorWithMessage:resultMsg]; } } #pragma mark - Interface Method
//- (void)paymentWithType:(WanPaymentType)type
//{
// self.paymentType = type;
//
// if (self.paymentType == WanPaymentTypeAliPay) {
// NSMutableDictionary *params = [NSMutableDictionary dictionary];
// [params setObject:kPPPaymentParamAliPayClient forKey:@"payment_type"];
// [params setObject:self.tradeNo forKey:@"order_sn"];
// [self requestPaymentURLWithParam:[NSDictionary dictionaryWithDictionary:params]];
// }
// else if (self.paymentType == WanPaymentTypeAliPayWAP) {
// NSMutableDictionary *params = [NSMutableDictionary dictionary];
// [params setObject:kPPPaymentParamAliPayWAP forKey:@"payment_type"];
// [params setObject:self.tradeNo forKey:@"order_sn"];
// [self requestPaymentURLWithParam:[NSDictionary dictionaryWithDictionary:params]];
// }
// else if (self.paymentType == WanPaymentTypeWXPay) {
// NSMutableDictionary *params = [NSMutableDictionary dictionary];
// [params setObject:kPPPaymentParamWXPayClient forKey:@"payment_type"];
// [params setObject:self.tradeNo forKey:@"order_sn"];
// [self requestPaymentURLWithParam:[NSDictionary dictionaryWithDictionary:params]];
// }
//}
#pragma mark - Handler Method - (void)openAliPayClientWithPaymentURL:(NSString *)paymentURL clientFlag:(NSString *)clientFlag { [[AlipaySDK defaultService] payOrder:paymentURL fromScheme:@"669SDKAliPay" callback:^(NSDictionary *dict) { if (dict) { NSLog(@"%@",dict); NSInteger statusCode = [dict[@"resultStatus"] integerValue]; NSString *msg = [NSString stringValue:dict[@"memo"]]; if (statusCode == 9000) { [self performSelector:@selector(paymentSuccess) withObject:self.tradeNo afterDelay:0.25f]; } else if (statusCode == 6001) { [self performSelector:@selector(paymentCancel) withObject:self.tradeNo afterDelay:0.25f]; } else { [self performSelector:@selector(paymentErrorWithMessage:) withObject:msg afterDelay:0.25f]; } } }]; } //- (void)openUPMPClientWithPaymentSN:(NSString *)paymentSN //{ // UIViewController *controller = [[[UIApplication sharedApplication] keyWindow] rootViewController]; // // if (![UPPayPlugin startPay:paymentSN mode:@"00" viewController:controller delegate:self]) { // [self paymentErrorWithMessage:@"抱歉,沒法加載銀聯控件,請關閉應用重試!"]; // } //} - (void)openWXClientWithPaymentURL:(NSDictionary *)paymentParams { NSString *parterId = [NSString stringValue:[paymentParams valueForKey:@"partnerid"]]; NSString *prePayId = [NSString stringValue:[paymentParams valueForKey:@"prepayid"]]; NSString *package = [NSString stringValue:[paymentParams valueForKey:@"package"]]; NSString *sign = [NSString stringValue:[paymentParams valueForKey:@"sign"]]; NSString *timestamp = [NSString stringValue:[paymentParams valueForKey:@"timestamp"]]; NSString *nonceStr = [NSString stringValue:[paymentParams valueForKey:@"noncestr"]]; self.wxAppKey = [NSString stringValue:[paymentParams valueForKey:@"appid"]]; if ([NSString isEmpty:parterId] || [NSString isEmpty:prePayId] || [NSString isEmpty:package] || [NSString isEmpty:sign] || [NSString isEmpty:timestamp] || [NSString isEmpty:nonceStr]) { [self paymentErrorWithMessage:@"缺乏關鍵參數,沒法執行微信支付!"]; return; } [WXApi registerApp:self.wxAppKey]; PayReq *request = [[PayReq alloc] init]; request.openID = self.wxAppKey; request.partnerId = parterId; request.prepayId = prePayId; request.package = package; request.nonceStr = nonceStr; request.timeStamp = [timestamp intValue]; request.sign = sign; if (![WXApi sendReq:request]) { [self paymentErrorWithMessage:@"抱歉,沒法打開微信。請您安裝最新版本微信"]; } } #pragma mark - 付款回調 - (void)paymentSuccess { if (self.delegate && [self.delegate respondsToSelector:@selector(paymentSuccess)]) { [self.delegate paymentSuccess]; } } - (void)paymentCancel { if (self.delegate && [self.delegate respondsToSelector:@selector(paymentCancel)]) { [self.delegate paymentCancel]; } } - (void)paymentErrorWithMessage:(NSString *)errorMessage { if (self.delegate && [self.delegate respondsToSelector:@selector(paymentResultWithError:)]) { [self.delegate paymentResultWithError:[NSError errorWithDomain:@"http://mobile.yx58.com/Api/Sdk/index" code:500 userInfo:@{NSLocalizedDescriptionKey:errorMessage}]]; } } // 支付寶客戶端支付後回調 - (BOOL)handleOpenURL:(NSURL *)url { NSString *query = [[NSString getString:[url query]] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; if (![NSString isEmpty:query]) { AlixPayResult *result = [[AlixPayResult alloc] initWithResultString:query]; if (result.statusCode == 9000) { [self performSelector:@selector(paymentSuccess) withObject:self.tradeNo afterDelay:0.25f]; } else if (result.statusCode == 6001) { [self performSelector:@selector(paymentCancel) withObject:self.tradeNo afterDelay:0.25f]; } else { [self performSelector:@selector(paymentErrorWithMessage:) withObject:result.statusMessage afterDelay:0.25f]; } } return NO; } // 銀聯控件回調 - (void)UPPayPluginResult:(NSString *)result { if ([result isEqualToString:@"success"]) { [self performSelector:@selector(paymentSuccess) withObject:self.tradeNo afterDelay:0.25f]; } else if ([result isEqualToString:@"cancel"]) { [self performSelector:@selector(paymentCancel) withObject:self.tradeNo afterDelay:0.25f]; } else { [self performSelector:@selector(paymentErrorWithMessage:) withObject:result afterDelay:0.5f]; } } - (void)onResp:(BaseResp *)resp { // 微信支付返回處理 if ([resp isKindOfClass:[PayResp class]]) { PayResp *response = (PayResp *)resp; NSLog(@"Pay Responder Code = %zd", response.errCode); [self wxpayResultCode:response.errCode]; } } // 微信支付客戶端回調 - (void)wxpayResultCode:(int)resultCode { NSString *errMsg = nil; if (resultCode == 0) { [self performSelector:@selector(paymentSuccess) withObject:self.tradeNo afterDelay:0.25f]; return; } else if (resultCode == -1) { errMsg = @"未知錯誤"; } else if (resultCode == -2) { errMsg = @"取消微信支付"; } else if (resultCode == -3) { errMsg = @"發送失敗"; } else if (resultCode == -4) { errMsg = @"受權失敗"; } else if (resultCode == -5) { errMsg = @"微信不支持"; } if (resultCode == -2) { [self performSelector:@selector(paymentCancel) withObject:self.tradeNo afterDelay:0.25f]; } else { [self performSelector:@selector(paymentErrorWithMessage:) withObject:@"微信支付失敗" afterDelay:0.25f]; } } @end
1.在調用後臺接口,生成訂單成功後調用一下代碼:
[[WanPaymentData instance] setDelegate:self]; [WanPaymentData instance].paymentType = paymentType; [[WanPaymentData instance] requestPaymentURLWithResult:dict];
2.遵照協議並實現代理方法:
#pragma mark --<WanPaymentDataDelegate> - (void)paymentSuccess{ [self removeFromSuperview]; if (self.paySuccessBlock) { self.paySuccessBlock(); } } - (void)paymentCancel{ [PPUIUtils showStateInWindow:@"您已放棄付款"]; } - (void)paymentResultWithError:(NSError *)error{ NSString *msg = [error localizedDescription]; [PPUIUtils showStateInWindow:msg]; }
3.在AppDelegate添加如下代碼
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
if ([url.host isEqualToString:@"safepay"]) {
return [[WanPaymentData instance] handleOpenURL:[NSURL URLWithString:url.absoluteString]];
}
return [WXApi handleOpenURL:url delegate:[WanPaymentData instance]];
}
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation{
if ([url.host isEqualToString:@"safepay"]) {
return [[WanPaymentData instance] handleOpenURL:[NSURL URLWithString:url.absoluteString]];
}
return [WXApi handleOpenURL:url delegate:[WanPaymentData instance]];
}
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
if ([url.host isEqualToString:@"safepay"]) {
return [[WanPaymentData instance] handleOpenURL:[NSURL URLWithString:url.absoluteString]];
}
return [WXApi handleOpenURL:url delegate:[WanPaymentData instance]];
}