實現微信支付的開發,iOS端裏面只需要四個步驟:
向服務端請求預支付,獲得prepayid以及noncestr;
把參數拼起來簽名;
發起支付請求;
處理支付結果。
iOS的微信SDK的接入:即爲“向微信註冊你的應用程序id”、“下載微信終端SDK文件”、“搭建開發環境”、“在代碼中使用開發工具包”。
詳情請參看iOS的接入指南:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417694084&token=96a6fb085dbc61bcafd732d1469e5fd0e20c9819&lang=zh_CN
導入微信支付庫:
開發者需要在工程中鏈接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib,最重要的庫是libc++.dylib;
iOS微信支付的具體流程:
- 向服務端請求預支付,獲得prepayid以及noncestr
//提交預支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams {
NSString *prepayid = nil;
//獲取提交支付
NSString *send = [self genPackage:prePayParams];
//輸出Debug Info
[debugInfo appendFormat:@"API鏈接:%@\n", payUrl];
[debugInfo appendFormat:@"發送的xml:%@\n", send];
//發送請求post xml數據
NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
//輸出Debug Info
[debugInfo appendFormat:@"服務器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
XMLHelper *xml = [XMLHelper alloc];
//開始解析
[xml startParse:res];
NSMutableDictionary *resParams = [xml getDict];
//判斷返回
NSString *return_code = [resParams objectForKey:@"return_code"];
NSString *result_code = [resParams objectForKey:@"result_code"];
if ([return_code isEqualToString:@"SUCCESS"]) {
//生成返回數據的簽名
NSString *sign = [self createMd5Sign:resParams ];
NSString *send_sign =[resParams objectForKey:@"sign"] ;
//驗證簽名正確性
if( [sign isEqualToString:send_sign]) {
if( [result_code isEqualToString:@"SUCCESS"]) {
//驗證業務處理狀態
prepayid = [resParams objectForKey:@"prepay_id"];
return_code = 0;
[debugInfo appendFormat:@"獲取預支付交易標示成功!\n"];
}
}else{
last_errcode = 1;
[debugInfo appendFormat:@"gen_sign=%@\n _sign=%@\n",sign,send_sign];
[debugInfo appendFormat:@"服務器返回簽名驗證錯誤!!!\n"];
}
}else{
last_errcode = 2;
[debugInfo appendFormat:@"接口返回錯誤!!!\n"];
}
return prepayid;
}
- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo {
//訂單標題,展示給用戶
NSString *order_name = @"展示給用戶的訂單標題";
//預付單參數訂單設置
srand( (unsigned)time(0) );
NSString *noncestr = [NSString stringWithFormat:@"%d", rand()];
NSString *orderno = orderNo;
NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
[packageParams setObject: appid forKey:@"appid"]; //開放平臺appid
[packageParams setObject: mchid forKey:@"mch_id"]; //商戶號
[packageParams setObject: @"APP-001" forKey:@"device_info"]; //支付設備號或門店號
[packageParams setObject: noncestr forKey:@"nonce_str"]; //隨機串
[packageParams setObject: @"APP" forKey:@"trade_type"]; //支付類型,固定爲APP
[packageParams setObject: order_name forKey:@"body"]; //訂單描述,展示給用戶
[packageParams setObject: NOTIFY_URL forKey:@"notify_url"]; //支付結果異步通知
[packageParams setObject: orderno forKey:@"out_trade_no"]; //商戶訂單號
[packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//發器支付的機器ip
[packageParams setObject: order_price forKey:@"total_fee"]; //訂單金額,單位爲分
//獲取prepayId(預支付交易會話標識)
NSString *prePayid;
prePayid = [self sendPrepay:packageParams];
if ( prePayid != nil) {
//獲取到prepayid後進行第二次簽名
NSString *package, *time_stamp, *nonce_str;
//設置支付參數
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@"%ld", now];
nonce_str = [WXUtil md5:time_stamp];
//重新按提交格式組包,微信客戶端暫只支持package=Sign=WXPay格式,須考慮升級後支持攜帶package具體參數的情況
package = @"Sign=WXPay";
//第二次簽名參數列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: appid forKey:@"appid"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: package forKey:@"package"];
[signParams setObject: mchid forKey:@"partnerid"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: prePayid forKey:@"prepayid"];
//生成簽名
NSString *sign = [self createMd5Sign:signParams];
//添加簽名
[signParams setObject: sign forKey:@"sign"];
[debugInfo appendFormat:@"第二步簽名成功,sign=%@\n",sign];
//返回參數列表
return signParams;
}else{
[debugInfo appendFormat:@"獲取prepayid失敗!\n"];
}
return nil;
}
- 把參數拼起來簽名
//創建package簽名
- (NSString*)createMd5Sign:(NSMutableDictionary*)dict {
NSMutableString *contentString =[NSMutableString string];
NSArray *keys = [dict allKeys];
//按字母順序排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//拼接字符串
for (NSString *categoryId in sortedArray) {
if (![[dict objectForKey:categoryId] isEqualToString:@""] && ![categoryId isEqualToString:@"sign"] && ![categoryId isEqualToString:@"key"])
{
[contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
}
}
//添加key字段
[contentString appendFormat:@"key=%@", spkey];
//得到MD5 sign簽名
NSString *md5Sign =[WXUtil md5:contentString];
//輸出Debug Info
[debugInfo appendFormat:@"MD5簽名字符串:\n%@\n\n",contentString];
return md5Sign;
}
//獲取package帶參數的簽名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams {
NSString *sign;
NSMutableString *reqPars=[NSMutableString string];
//生成簽名
sign = [self createMd5Sign:packageParams];
//生成xml的package
NSArray *keys = [packageParams allKeys];
[reqPars appendString:@"<xml>\n"];
for (NSString *categoryId in keys) {
[reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
}
[reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
return [NSString stringWithString:reqPars];
}
- 發起支付請求
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//支付結果通知註冊
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
}
//調用微信支付
- (void)viewDidLoad {
[super viewDidLoad];
[self WXPay];
}
#pragma mark -- 發起”微信支付“請求
- (void)WXPay {
if (![WXApi isWXAppInstalled]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您還沒有安裝微信" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//跳轉到微信的下載安裝地址
}];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
return ;
}
YDWWeChatPayResquest *req = [YDWWeChatPayResquest new];
//初始化支付簽名對象
[req init:APP_ID mch_id:MCH_ID];
//設置密鑰
[req setKey:PARTNER_ID];
//獲取到實際調起微信支付的參數後,在app端調起支付
NSInteger payTheAmount;//支付金額
NSString *orderMeony = [NSString stringWithFormat:@"%ld",payTheAmount];
NSDictionary *orderDic;//支付訂單
NSString *orderNo = [orderDic objectForKey:@"orderNumber"];
NSMutableDictionary *dict = [req sendPay_WithPrice:orderMeony orderNo: orderNo];
if(dict == nil){
//錯誤提示
NSString *debug = [req getDebugifo];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:debug message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}else{
NSMutableString *stamp = [dict objectForKey:@"timestamp"];
//調起微信支付
PayReq* req = [[PayReq alloc] init];
req.openID = [dict objectForKey:@"appid"];
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"];
[WXApi sendReq:req];
}
}
- (void)weixinPay {
YDWWeixinPayParams *signParams = [[YDWWeixinPayParams alloc] initWithPrepayid:self.prepay_id noncestr:self.nonce_str];
//調起微信支付
PayReq *req = [[PayReq alloc] init];
req.openID = signParams.appid;
req.partnerId = signParams.partnerid;
req.prepayId = signParams.prepayid;
req.nonceStr = signParams.noncestr;
req.timeStamp = signParams.timestamp.intValue;
req.package = signParams.package;
req.sign = [signParams sign];
[WXApi sendReq:req];
}
#pragma mark - 支付結果通知信息
- (void)getOrderPayResult:(NSNotification *)notification{
if ([notification.object isEqualToString:@"success"]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"您已成功支付啦!" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}
else
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"支付失敗,可在待付款訂單中查看" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}
}
//移除通知
- (void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
- 處理支付結果,在AppDelegate中做的工作:
1、導入#import “WXApi.h”和#import “WXApiObject.h”,並遵守WXApiDelegate協議,要使你的程序啓動後微信終端能響應你的程序,必須在代碼中向微信終端註冊你的id:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"WXAppId" withDescription:@"YDWWXPayDes"];
return YES;
}
2、重寫AppDelegate的handleOpenURL和openURL方法:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
if ([url.absoluteString hasPrefix:Weixin_Appid]) {
return [WXApi handleOpenURL:url delegate:self];
}
return YES;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [WXApi handleOpenURL:url delegate:self];
}
3、處理結果:
- (void)onResp:(BaseResp *)resp {
NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
NSString *strTitle;
if([resp isKindOfClass:[SendMessageToWXResp class]]) {
strTitle = [NSString stringWithFormat:@"發送媒體消息結果"];
}
if([resp isKindOfClass:[PayResp class]])
{
//支付返回結果,實際支付結果需要去微信服務器端查詢
strTitle = [NSString stringWithFormat:@"支付結果"];
switch (resp.errCode) {
case WXSuccess:{
strMsg = @"支付結果:成功!";
NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"success"];
[[NSNotificationCenter defaultCenter] postNotification:notification];
break;
}
default:{
strMsg = [NSString stringWithFormat:@"支付結果:失敗!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
NSLog(@"錯誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"fail"];
[[NSNotificationCenter defaultCenter] postNotification:notification];
break;
}
}
}
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
// [alert show];
}
常見的問題:
如果跳轉到微信裏之只彈出了一個確定按鈕,那麼這時候需要檢查幾個方面:
1、appid,mch_id,partner_id是否設置正確。mch_id對應的key其實是partnerid,partner_id對應的key其實是key;
2、timestamp 應爲10位;
3、簽名需要排序,並用md5加密。
最後附上重要的類的全部代碼:
AppDelegate:
// AppDelegate.h
// 微信支付
//
// Created by YDW on 16/3/28.
// Copyright © 2016年 IZHUO.NET. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "WXApi.h"
#import "WXApiObject.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate,WXApiDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
// AppDelegate.m
// 微信支付
//
// Created by YDW on 16/3/28.
// Copyright © 2016年 IZHUO.NET. All rights reserved.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"WXAppId" withDescription:@"YDWWXPayDes"];
return YES;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [WXApi handleOpenURL:url delegate:self];
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [WXApi handleOpenURL:url delegate:self];
}
- (void)onResp:(BaseResp *)resp {
NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
NSString *strTitle;
if([resp isKindOfClass:[SendMessageToWXResp class]]) {
strTitle = [NSString stringWithFormat:@"發送媒體消息結果"];
}
if([resp isKindOfClass:[PayResp class]])
{
//支付返回結果,實際支付結果需要去微信服務器端查詢
strTitle = [NSString stringWithFormat:@"支付結果"];
switch (resp.errCode) {
case WXSuccess:{
strMsg = @"支付結果:成功!";
NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"success"];
[[NSNotificationCenter defaultCenter] postNotification:notification];
break;
}
default:{
strMsg = [NSString stringWithFormat:@"支付結果:失敗!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
NSLog(@"錯誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
NSNotification *notification = [NSNotification notificationWithName:@"ORDER_PAY_NOTIFICATION" object:@"fail"];
[[NSNotificationCenter defaultCenter] postNotification:notification];
break;
}
}
}
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle message:strMsg delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
// [alert show];
}
YDWWeChatPayResquest:
// YDWWeChatPayResquest.h
// 微信支付
//
// Created by YDW on 16/3/28.
// Copyright © 2016年 IZHUO.NET. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "WXUtil.h"
#import "ApiXml.h"
/*
* 賬號的賬戶資料:更改商戶後的相關參數後可以使用
*/
#define APP_ID @"你的APP的ID" //APPID
#define APP_SECRET @"你的APP的secret" //appsecret
#define MCH_ID @"商戶號" //商戶號,填寫商戶對應參數
#define PARTNER_ID @"商戶API密鑰" //商戶API密鑰,填寫相應參數
#define NOTIFY_URL @"回調頁面地址" //支付結果回調頁面
#define SP_URL @"服務器端支付數據地址"//獲取服務器端支付數據地址(商戶自定義)
@interface YDWWeChatPayResquest : NSObject {
//預支付的url地址
NSString *payUrl;
//lash_errcode;
long last_errcode;
//debug信息
NSMutableString *debugInfo;
NSString *appid,*mchid,*spkey;
}
- (BOOL)init:(NSString *)app_id mch_id:(NSString *)mch_id;
- (NSString *)getDebugifo;
- (long)getLasterrCode;
//設置商戶密鑰
- (void)setKey:(NSString *)key;
//創建package簽名
- (NSString*)createMd5Sign:(NSMutableDictionary*)dict;
//獲取package帶參數的簽名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams;
//提交預支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams;
- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo;
//簽名實例測試
//- (NSMutableDictionary *)sendPay_demo;
@end
// YDWWeChatPayResquest.m
// 微信支付
//
// Created by YDW on 16/3/28.
// Copyright © 2016年 IZHUO.NET. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "YDWWeChatPayResquest.h"
@implementation YDWWeChatPayResquest
- (BOOL)init:(NSString *)app_id mch_id:(NSString *)mch_id {
payUrl = @"https://api.mch.weixin.qq.com/pay/unifiedorder";
if (debugInfo == nil){
debugInfo = [NSMutableString string];
}
[debugInfo setString:@""];
appid = app_id;
mchid = mch_id;
return YES;
}
//設置商戶密鑰
- (void)setKey:(NSString *)key {
spkey = [NSString stringWithString:key];
}
//獲取debug信息
- (NSString*)getDebugifo {
NSString *res = [NSString stringWithString:debugInfo];
[debugInfo setString:@""];
return res;
}
//獲取最後服務返回錯誤代碼
- (long)getLasterrCode {
return last_errcode;
}
//創建package簽名
- (NSString*)createMd5Sign:(NSMutableDictionary*)dict {
NSMutableString *contentString =[NSMutableString string];
NSArray *keys = [dict allKeys];
//按字母順序排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//拼接字符串
for (NSString *categoryId in sortedArray) {
if (![[dict objectForKey:categoryId] isEqualToString:@""] && ![categoryId isEqualToString:@"sign"] && ![categoryId isEqualToString:@"key"])
{
[contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
}
}
//添加key字段
[contentString appendFormat:@"key=%@", spkey];
//得到MD5 sign簽名
NSString *md5Sign =[WXUtil md5:contentString];
//輸出Debug Info
[debugInfo appendFormat:@"MD5簽名字符串:\n%@\n\n",contentString];
return md5Sign;
}
//獲取package帶參數的簽名包
- (NSString *)genPackage:(NSMutableDictionary*)packageParams {
NSString *sign;
NSMutableString *reqPars=[NSMutableString string];
//生成簽名
sign = [self createMd5Sign:packageParams];
//生成xml的package
NSArray *keys = [packageParams allKeys];
[reqPars appendString:@"<xml>\n"];
for (NSString *categoryId in keys) {
[reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
}
[reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
return [NSString stringWithString:reqPars];
}
//提交預支付
- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams {
NSString *prepayid = nil;
//獲取提交支付
NSString *send = [self genPackage:prePayParams];
//輸出Debug Info
[debugInfo appendFormat:@"API鏈接:%@\n", payUrl];
[debugInfo appendFormat:@"發送的xml:%@\n", send];
//發送請求post xml數據
NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
//輸出Debug Info
[debugInfo appendFormat:@"服務器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
XMLHelper *xml = [XMLHelper alloc];
//開始解析
[xml startParse:res];
NSMutableDictionary *resParams = [xml getDict];
//判斷返回
NSString *return_code = [resParams objectForKey:@"return_code"];
NSString *result_code = [resParams objectForKey:@"result_code"];
if ([return_code isEqualToString:@"SUCCESS"]) {
//生成返回數據的簽名
NSString *sign = [self createMd5Sign:resParams ];
NSString *send_sign =[resParams objectForKey:@"sign"] ;
//驗證簽名正確性
if( [sign isEqualToString:send_sign]) {
if( [result_code isEqualToString:@"SUCCESS"]) {
//驗證業務處理狀態
prepayid = [resParams objectForKey:@"prepay_id"];
return_code = 0;
[debugInfo appendFormat:@"獲取預支付交易標示成功!\n"];
}
}else{
last_errcode = 1;
[debugInfo appendFormat:@"gen_sign=%@\n _sign=%@\n",sign,send_sign];
[debugInfo appendFormat:@"服務器返回簽名驗證錯誤!!!\n"];
}
}else{
last_errcode = 2;
[debugInfo appendFormat:@"接口返回錯誤!!!\n"];
}
return prepayid;
}
- (NSMutableDictionary *)sendPay_WithPrice:(NSString *)order_price orderNo:(NSString *)orderNo {
//訂單標題,展示給用戶
NSString *order_name = @"展示給用戶的訂單標題";
//預付單參數訂單設置
srand( (unsigned)time(0) );
NSString *noncestr = [NSString stringWithFormat:@"%d", rand()];
NSString *orderno = orderNo;
NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
[packageParams setObject: appid forKey:@"appid"]; //開放平臺appid
[packageParams setObject: mchid forKey:@"mch_id"]; //商戶號
[packageParams setObject: @"APP-001" forKey:@"device_info"]; //支付設備號或門店號
[packageParams setObject: noncestr forKey:@"nonce_str"]; //隨機串
[packageParams setObject: @"APP" forKey:@"trade_type"]; //支付類型,固定爲APP
[packageParams setObject: order_name forKey:@"body"]; //訂單描述,展示給用戶
[packageParams setObject: NOTIFY_URL forKey:@"notify_url"]; //支付結果異步通知
[packageParams setObject: orderno forKey:@"out_trade_no"]; //商戶訂單號
[packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//發器支付的機器ip
[packageParams setObject: order_price forKey:@"total_fee"]; //訂單金額,單位爲分
//獲取prepayId(預支付交易會話標識)
NSString *prePayid;
prePayid = [self sendPrepay:packageParams];
if ( prePayid != nil) {
//獲取到prepayid後進行第二次簽名
NSString *package, *time_stamp, *nonce_str;
//設置支付參數
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@"%ld", now];
nonce_str = [WXUtil md5:time_stamp];
//重新按提交格式組包,微信客戶端暫只支持package=Sign=WXPay格式,須考慮升級後支持攜帶package具體參數的情況
package = @"Sign=WXPay";
//第二次簽名參數列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: appid forKey:@"appid"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: package forKey:@"package"];
[signParams setObject: mchid forKey:@"partnerid"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: prePayid forKey:@"prepayid"];
//生成簽名
NSString *sign = [self createMd5Sign:signParams];
//添加簽名
[signParams setObject: sign forKey:@"sign"];
[debugInfo appendFormat:@"第二步簽名成功,sign=%@\n",sign];
//返回參數列表
return signParams;
}else{
[debugInfo appendFormat:@"獲取prepayid失敗!\n"];
}
return nil;
}
@end
調用微信支付的頁面:
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self WXPay];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//支付結果通知註冊
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:@"ORDER_PAY_NOTIFICATION" object:nil];
}
#pragma mark -- 發起”微信支付“請求
- (void)WXPay {
if (![WXApi isWXAppInstalled]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"您還沒有安裝微信" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//跳轉到微信的下載安裝地址
}];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
return ;
}
YDWWeChatPayResquest *req = [YDWWeChatPayResquest new];
//初始化支付簽名對象
[req init:APP_ID mch_id:MCH_ID];
//設置密鑰
[req setKey:PARTNER_ID];
//獲取到實際調起微信支付的參數後,在app端調起支付
NSInteger payTheAmount;//支付金額
NSString *orderMeony = [NSString stringWithFormat:@"%ld",payTheAmount];
NSDictionary *orderDic;//支付訂單
NSString *orderNo = [orderDic objectForKey:@"orderNumber"];
NSMutableDictionary *dict = [req sendPay_WithPrice:orderMeony orderNo: orderNo];
if(dict == nil){
//錯誤提示
NSString *debug = [req getDebugifo];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:debug message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}else{
NSMutableString *stamp = [dict objectForKey:@"timestamp"];
//調起微信支付
PayReq* req = [[PayReq alloc] init];
req.openID = [dict objectForKey:@"appid"];
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"];
[WXApi sendReq:req];
}
}
#pragma mark - 支付結果通知信息
- (void)getOrderPayResult:(NSNotification *)notification{
if ([notification.object isEqualToString:@"success"]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"恭喜" message:@"您已成功支付啦!" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}
else
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"支付失敗,可在待付款訂單中查看" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:sureAction];
[self.navigationController presentViewController:alert animated:YES completion:nil];
}
}
//移除通知
- (void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
@end