支付寶流程
06FB153E-E539-4589-B7C7-2F9DA5923AC4.png
F511C2F7-2EC1-44C2-92E5-1BF3785E20CE.png
2ABA3F53-0820-4E89-920F-254465EDC742.png
77C28A67-B4E8-481B-A258-2471021B5980.png
模擬訂單模擬支付行為
10C8BF8A-66F8-4EC7-8ABC-161866D972EF.png
557CC65F-4253-4CB7-8089-81A5C468974C.png
E279A377-33FF-494D-810A-6506815D3E58.png
下圖中:支付類型----移動端只負責 "1.支付" 就行,其余后臺管
B3E557A5-F312-409E-BC4C-7BFD6B1FB4A3.png
7A961896-ABBC-4F4B-BEB8-80B524BB3A1E.png
FFDA9D60-6589-4912-879E-8919684FAC3F.png
其中處理訂單號代碼如下
E96A92E9-17CA-4999-AB03-7C22636F03F1.png
通過各種算法生成隨機訂單號
EFF8DB1D-B063-4B3C-95C5-168203F6718A.png
二級商戶
720A8BC3-4E5C-4730-8365-D186CAA32FE5.png
微信支付流程
#import "AppDelegate.h"
#import "WXApi.h"
@interface AppDelegate ()<WXApiDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//開啟AFN框架內網路指示器(小菊花)
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
//定義頂部20高的狀態欄屬性
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
//設置圖片緩存策略
[SDImageCache sharedImageCache].maxCacheAge = 1024*1024*10;
//向微信注冊
[WXApi registerApp:@"wx1a851bd5c91204b3"];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
LoginController *loginController = [[LoginController alloc] init];
ZYNavigationController *nav = [[ZYNavigationController alloc] initWithRootViewController:loginController];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [WXApi handleOpenURL:url delegate:self];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [WXApi handleOpenURL:url delegate:self];
}
- (void)onResp:(BaseResp *)resp
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"PAY_FINISH_NOTIF" object:nil]
//如果支付成功則去后臺查詢支付結果再展示用戶實際支付結果。注意 一定不能以客戶端返回作為用戶支付的結果,應以服務器端的接收的支付通知或查詢API返回的結果為準。
NSString *strMsg = [NSString stringWithFormat:@"支付結果"];
switch (resp.errCode) {
case WXSuccess:
strMsg = @"支付結果:成功!";
NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
//從服務器端再次確認支付是否成功
[self makeSureChargeStatus];
break;
default:
strMsg = [NSString stringWithFormat:@"支付結果:失敗!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
NSLog(@"錯誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
break;
}
}
//從服務器端再次確認支付是否成功
- (void)makeSureChargeStatus
{
/*
### 查詢充值結果
* 地址
http://dyt-win/greapost/rest/charge/status
* 參數
{"userId":"a0d8ec16f42b11e6b50ed279e40c8da1","chargeId":"a0d8ec16f42b11e6b50ed279e40c8da1"}
* 返回值
{"success":true,"state":"SUCCESS"}
ps: state 可選值
PAYSTATE_PREFAIL = "PREFAIL";
PAYSTATE_NOTPAY = "NOTPAY";
PAYSTATE_REFUND = "REFUND";
PAYSTATE_SUCCESS = "SUCCESS";
PAYSTATE_CLOSED = "CLOSED";
PAYSTATE_USERPAYING = "REVOKED";
PAYSTATE_PAYERROR = "REVOKED";
PREFAIL-統一下單失敗
SUCCESS—支付成功
REFUND—轉入退款
NOTPAY—未支付
CLOSED—已關閉
REVOKED—已撤銷(刷卡支付)
USERPAYING--用戶支付中
PAYERROR--支付失敗(其他原因,如銀行返回失敗)
*/
NSDictionary *parameters = @{
@"userId": [Tool sharedTool].userID,
@"chargeId": [Tool sharedTool].chargeId
};
[HttpRequest postWithURLString:@"greapost/rest/charge/status" parameters:parameters success:^(id responseObject) {
NSLog(@"支付結果查詢:%@",responseObject);
if (responseObject[@"success"]) {
[self showPayState:responseObject[@"state"]];
} else {
[Tool showErrorSVProgressHUDWithStatus:responseObject[@"msg"]];
}
} failure:^(NSError *error) {
[Tool showErrorSVProgressHUDWithStatus:ServerNetworkError];
}];
}
//獲取支付狀態
- (void)showPayState:(NSString *)state
{
if ([state isEqualToString:@"NOTPAY"]) {
[Tool showWarningSVProgressHUDWithStatus:@"未支付" time:2.0];
return;
}
if ([state isEqualToString:@"SUCCESS"]) {
[Tool showSuccessSVProgressHUDWithStatus:@"支付成功"];
return;
}
if ([state isEqualToString:@"REFUND"]) {
[Tool showWarningSVProgressHUDWithStatus:@"轉入退款" time:2.0];
return;
}
if ([state isEqualToString:@"REVOKED"]) {
[Tool showWarningSVProgressHUDWithStatus:@"已撤銷" time:2.0];
return;
}
if ([state isEqualToString:@"CLOSED"]) {
[Tool showWarningSVProgressHUDWithStatus:@"已關閉" time:2.0];
return;
}
if ([state isEqualToString:@"PREFAIL"]) {
[Tool showWarningSVProgressHUDWithStatus:@"統一下單失敗" time:2.0];
return;
}
if ([state isEqualToString:@"USERPAYING"]) {
[Tool showWarningSVProgressHUDWithStatus:@"用戶支付中" time:2.0];
return;
}
if ([state isEqualToString:@"PAYERROR"]) {
[Tool showWarningSVProgressHUDWithStatus:@"支付失敗(其他原因,如銀行返回失敗)" time:2.0];
return;
}
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[[SDImageCache sharedImageCache] clearMemory];
[[SDWebImageManager sharedManager] cancelAll];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
#import "ChargeController.h"
#import "WXApi.h"
@interface ChargeController ()<ChoosePayViewDelegate>
@property (nonatomic, weak) ChoosePayView *choosePayView;
@end
@implementation ChargeController
- (void)viewDidLoad {
[super viewDidLoad];
[self addSubViews];
}
- (void)addSubViews
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(popViewController) name:@"PAY_FINISH_NOTIF" object:nil];
self.title = @"充值";
}
- (void)popViewController
{
[self.navigationController popViewControllerAnimated:YES];
}
- (void)choosePayView
{
if(!_choosePayView){
_choosePayView = [[ChoosePayView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT)];
choosePayView.delegate = self;
choosePayView.money = money;//用戶選中的充值面額
}
return _choosePayView;
}
//點擊充值按鈕,動畫彈出微信.支付寶方式選中框
- (void)clickChargeButton:(UIButton *)ban
{
//懶加載添加,保證只添加一次
UIApplication *ap = [UIApplication sharedApplication];
[ap.keyWindow addSubview:self.choosePayView];
[UIView animateWithDuration:0.3 animations:^{
self.choosePayView.top = 0;
} completion:^(BOOL finished) {
count = 0;
}];
}
#pragma mark - choosePayViewDelegate
//選擇支付方式代理方法
- (void)chooseAlipayOrWeChatPay:(PayType)payType
{
/*
### 充值
* 地址
http://dyt-win/greapost/rest/charge/unifiedorder
* 參數
{"userId":"a0d8ec16f42b11e6b50ed279e40c8da1","totalFee":"0.01"}
* 返回值
{"success":true,"package":"Sign=WXPay","appid":"wx1a851bd5c91204b3","sign":"773CC5445E6C38CF9D8B7BEDE2D5DC33","prepayid":"wx20170217141956a16afe8fb70522432780","partnerid":"1243435702","noncestr":"77qous9c45mceab6kuw86705igouz0m7","timestamp":"1487312412"}
*/
[self.choosePayView removeFromSuperview];
if (payType == kALiPayTYPE) {
NSLog(@"選中了支付寶支付方式");
[Tool showWarningSVProgressHUDWithStatus:@"暫時不支持支付寶支付" time:2.0];
} else {
NSLog(@"選中了微信支付方式");
//調起支付: 商戶服務器生成支付訂單,先調用【統一下單API】生成預付單,獲取到prepay_id后將參數再次簽名傳輸給APP發起支付。以下是調起微信支付的關鍵代碼:
NSDictionary *parameters = @{
//傳入用戶id
@"userId": [Tool sharedTool].userID,
//傳入選中充值面額
@"totalFee": self.choosePayView.money
};
[HttpRequest postWithURLString:@"greapost/rest/charge/unifiedorder" parameters:parameters success:^(id responseObject) {
/*
支付結果: {
appid = wx1a851bd5c91204b3;
noncestr = 8bv12duoidtoqo0pqpdz1z41wy9dxdse;
package = "Sign=WXPay";
partnerid = 1243435702;
prepayid = wx201702171457555d8a431e470433379896;
sign = B2DB5E26D59B19134EF3660AC6C2711F;
success = 1;
timestamp = 1487314687;
chargeId = 3d626bc3f5e211e6bc070050563731d8;
}
*/
NSLog(@"支付結果: %@",responseObject);
if ([responseObject[@"success"] boolValue]) {
[[Tool sharedTool] setChargeId:responseObject[@"chargeId"]];
//服務器返回訂單成功后, 進行微信支付
PayReq *request = [[PayReq alloc] init];
request.partnerId = responseObject[@"partnerid"];
request.prepayId= responseObject[@"prepayid"];
request.package = @"Sign=WXPay";
request.nonceStr= responseObject[@"noncestr"];
request.timeStamp= [responseObject[@"timestamp"] intValue];
request.sign= responseObject[@"sign"];
if ([WXApi isWXAppInstalled]) {
[WXApi sendReq:request];
} else {
[Tool showWarningSVProgressHUDWithStatus:@"未安裝微信應用" time:2.0];
}
} else {
[Tool showErrorSVProgressHUDWithStatus:[NSString stringWithFormat: @"%@",responseObject[@"msg"]]];
}
} failure:^(NSError *error) {
NSLog(@"服務器請求訂單失敗 error:%@",error.localizedDescription);
// [Tool showErrorSVProgressHUDWithStatus:ServerNetworkError];
}];
}
}
- (void)dismissChoosePayView
{
[self.choosePayView removeFromSuperview];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end